2 * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 #include <openssl/opensslconf.h> /* SIXTY_FOUR_BIT_LONG, ... */
11 #include <openssl/err.h>
12 #include <openssl/pem.h> /* PEM_BUFSIZE */
13 #include <openssl/pkcs12.h> /* PKCS8_encrypt() */
14 #include <openssl/types.h>
15 #include <openssl/x509.h> /* i2d_X509_PUBKEY_bio() */
16 #include "crypto/bn.h" /* bn_get_words() */
17 #include "crypto/ecx.h"
18 #include "prov/bio.h" /* ossl_prov_bio_printf() */
19 #include "prov/implementations.h"
20 #include "prov/providercommonerr.h" /* PROV_R_READ_KEY */
21 #include "serializer_local.h"
23 static PKCS8_PRIV_KEY_INFO
*
24 ossl_prov_p8info_from_obj(const void *obj
, int obj_nid
,
27 int (*k2d
)(const void *obj
,
28 unsigned char **pder
))
30 /* der, derlen store the key DER output and its length */
31 unsigned char *der
= NULL
;
33 /* The final PKCS#8 info */
34 PKCS8_PRIV_KEY_INFO
*p8info
= NULL
;
37 if ((p8info
= PKCS8_PRIV_KEY_INFO_new()) == NULL
38 || (derlen
= k2d(obj
, &der
)) <= 0
39 || !PKCS8_pkey_set0(p8info
, OBJ_nid2obj(obj_nid
), 0,
40 params_type
, params
, der
, derlen
)) {
41 ERR_raise(ERR_LIB_PROV
, ERR_R_MALLOC_FAILURE
);
42 PKCS8_PRIV_KEY_INFO_free(p8info
);
50 static X509_SIG
*ossl_prov_encp8_from_p8info(PKCS8_PRIV_KEY_INFO
*p8info
,
51 struct pkcs8_encrypt_ctx_st
*ctx
)
54 char buf
[PEM_BUFSIZE
];
55 const void *kstr
= ctx
->cipher_pass
;
56 size_t klen
= ctx
->cipher_pass_length
;
58 if (ctx
->cipher
== NULL
)
62 if (!ctx
->cb(buf
, sizeof(buf
), &klen
, NULL
, ctx
->cbarg
)) {
63 ERR_raise(ERR_LIB_PROV
, PROV_R_READ_KEY
);
68 /* NID == -1 means "standard" */
69 p8
= PKCS8_encrypt(-1, ctx
->cipher
, kstr
, klen
, NULL
, 0, 0, p8info
);
71 OPENSSL_cleanse(buf
, klen
);
75 static X509_SIG
*ossl_prov_encp8_from_obj(const void *obj
, int obj_nid
,
78 int (*k2d
)(const void *obj
,
79 unsigned char **pder
),
80 struct pkcs8_encrypt_ctx_st
*ctx
)
82 PKCS8_PRIV_KEY_INFO
*p8info
=
83 ossl_prov_p8info_from_obj(obj
, obj_nid
, params
, params_type
, k2d
);
84 X509_SIG
*p8
= ossl_prov_encp8_from_p8info(p8info
, ctx
);
86 PKCS8_PRIV_KEY_INFO_free(p8info
);
90 static X509_PUBKEY
*ossl_prov_pubkey_from_obj(const void *obj
, int obj_nid
,
93 int (*k2d
)(const void *obj
,
94 unsigned char **pder
))
96 /* der, derlen store the key DER output and its length */
97 unsigned char *der
= NULL
;
99 /* The final X509_PUBKEY */
100 X509_PUBKEY
*xpk
= NULL
;
103 if ((xpk
= X509_PUBKEY_new()) == NULL
104 || (derlen
= k2d(obj
, &der
)) <= 0
105 || !X509_PUBKEY_set0_param(xpk
, OBJ_nid2obj(obj_nid
),
106 params_type
, params
, der
, derlen
)) {
107 ERR_raise(ERR_LIB_PROV
, ERR_R_MALLOC_FAILURE
);
108 X509_PUBKEY_free(xpk
);
116 OSSL_OP_keymgmt_new_fn
*ossl_prov_get_keymgmt_new(const OSSL_DISPATCH
*fns
)
118 /* Pilfer the keymgmt dispatch table */
119 for (; fns
->function_id
!= 0; fns
++)
120 if (fns
->function_id
== OSSL_FUNC_KEYMGMT_NEW
)
121 return OSSL_get_OP_keymgmt_new(fns
);
126 OSSL_OP_keymgmt_free_fn
*ossl_prov_get_keymgmt_free(const OSSL_DISPATCH
*fns
)
128 /* Pilfer the keymgmt dispatch table */
129 for (; fns
->function_id
!= 0; fns
++)
130 if (fns
->function_id
== OSSL_FUNC_KEYMGMT_FREE
)
131 return OSSL_get_OP_keymgmt_free(fns
);
136 OSSL_OP_keymgmt_import_fn
*ossl_prov_get_keymgmt_import(const OSSL_DISPATCH
*fns
)
138 /* Pilfer the keymgmt dispatch table */
139 for (; fns
->function_id
!= 0; fns
++)
140 if (fns
->function_id
== OSSL_FUNC_KEYMGMT_IMPORT
)
141 return OSSL_get_OP_keymgmt_import(fns
);
146 # ifdef SIXTY_FOUR_BIT_LONG
147 # define BN_FMTu "%lu"
148 # define BN_FMTx "%lx"
151 # ifdef SIXTY_FOUR_BIT
152 # define BN_FMTu "%llu"
153 # define BN_FMTx "%llx"
156 # ifdef THIRTY_TWO_BIT
157 # define BN_FMTu "%u"
158 # define BN_FMTx "%x"
161 int ossl_prov_print_labeled_bignum(BIO
*out
, const char *label
,
165 const char *post_label_spc
= " ";
177 bytes
= BN_num_bytes(bn
);
178 words
= bn_get_words(bn
);
179 neg
= BN_is_negative(bn
) ? "-" : "";
182 return ossl_prov_bio_printf(out
, "%s%s0\n", label
, post_label_spc
);
184 if (BN_num_bytes(bn
) <= BN_BYTES
)
185 return ossl_prov_bio_printf(out
,
186 "%s%s%s" BN_FMTu
" (%s0x" BN_FMTx
")\n",
187 label
, post_label_spc
, neg
, words
[0],
193 if (ossl_prov_bio_printf(out
, "%s%s\n", label
, neg
) <= 0)
196 /* Keep track of how many bytes we have printed out so far */
200 * OpenSSL BIGNUMs are little endian limbs, so we print them last to
202 * i is used as limb index, j is used as the "byte index" in the limb
204 for (i
= bytes
/ BN_BYTES
- 1; i
>= 0; i
--) {
205 BN_ULONG l
= words
[i
];
208 for (j
= BN_BYTES
- 1; j
>= 0; j
--) {
210 int b
= ((l
& (0xffLU
<< o
)) >> o
) & 0xff;
212 /* Indent every new line with 4 spaces */
215 if (ossl_prov_bio_printf(out
, "\n") <= 0)
217 if (ossl_prov_bio_printf(out
, " ") <= 0)
222 * Upper bit set, then we print an extra zero and pretend the
223 * BIGNUM was one byte longer
225 if (n
== 0 && b
> 127) {
226 if (ossl_prov_bio_printf(out
, "%02x:", 0) <= 0)
233 if (ossl_prov_bio_printf(out
, "%02x:", b
) <= 0)
236 if (ossl_prov_bio_printf(out
, "%02x", b
) <= 0)
241 if (ossl_prov_bio_printf(out
, "\n") <= 0)
247 /* Number of octets per line */
248 #define LABELED_BUF_PRINT_WIDTH 15
250 int ossl_prov_print_labeled_buf(BIO
*out
, const char *label
,
251 const unsigned char *buf
, size_t buflen
)
255 if (ossl_prov_bio_printf(out
, "%s\n", label
) <= 0)
258 for (i
= 0; i
< buflen
; i
++) {
259 if ((i
% LABELED_BUF_PRINT_WIDTH
) == 0) {
260 if (i
> 0 && ossl_prov_bio_printf(out
, "\n") <= 0)
262 if (ossl_prov_bio_printf(out
, " ") <= 0)
266 if (ossl_prov_bio_printf(out
, "%02x%s", buf
[i
],
267 (i
== buflen
- 1) ? "" : ":") <= 0)
270 if (ossl_prov_bio_printf(out
, "\n") <= 0)
276 /* p2s = param to asn1, k2d = key to der */
277 int ossl_prov_write_priv_der_from_obj(BIO
*out
, const void *obj
, int obj_nid
,
278 int (*p2s
)(const void *obj
, int nid
,
281 int (*k2d
)(const void *obj
,
282 unsigned char **pder
),
283 struct pkcs8_encrypt_ctx_st
*ctx
)
287 int strtype
= V_ASN1_UNDEF
;
289 if (p2s
!= NULL
&& !p2s(obj
, obj_nid
, &str
, &strtype
))
292 if (ctx
->cipher_intent
) {
294 ossl_prov_encp8_from_obj(obj
, obj_nid
, str
, strtype
, k2d
, ctx
);
297 ret
= i2d_PKCS8_bio(out
, p8
);
301 PKCS8_PRIV_KEY_INFO
*p8info
=
302 ossl_prov_p8info_from_obj(obj
, obj_nid
, str
, strtype
, k2d
);
305 ret
= i2d_PKCS8_PRIV_KEY_INFO_bio(out
, p8info
);
307 PKCS8_PRIV_KEY_INFO_free(p8info
);
313 int ossl_prov_write_priv_pem_from_obj(BIO
*out
, const void *obj
, int obj_nid
,
314 int (*p2s
)(const void *obj
, int nid
,
317 int (*k2d
)(const void *obj
,
318 unsigned char **pder
),
319 struct pkcs8_encrypt_ctx_st
*ctx
)
323 int strtype
= V_ASN1_UNDEF
;
325 if (p2s
!= NULL
&& !p2s(obj
, obj_nid
, &str
, &strtype
))
328 if (ctx
->cipher_intent
) {
329 X509_SIG
*p8
= ossl_prov_encp8_from_obj(obj
, obj_nid
, str
, strtype
,
333 ret
= PEM_write_bio_PKCS8(out
, p8
);
337 PKCS8_PRIV_KEY_INFO
*p8info
=
338 ossl_prov_p8info_from_obj(obj
, obj_nid
, str
, strtype
, k2d
);
341 ret
= PEM_write_bio_PKCS8_PRIV_KEY_INFO(out
, p8info
);
343 PKCS8_PRIV_KEY_INFO_free(p8info
);
349 int ossl_prov_write_pub_der_from_obj(BIO
*out
, const void *obj
, int obj_nid
,
350 int (*p2s
)(const void *obj
, int nid
,
353 int (*k2d
)(const void *obj
,
354 unsigned char **pder
))
358 int strtype
= V_ASN1_UNDEF
;
359 X509_PUBKEY
*xpk
= NULL
;
361 if (p2s
!= NULL
&& !p2s(obj
, obj_nid
, &str
, &strtype
))
364 xpk
= ossl_prov_pubkey_from_obj(obj
, obj_nid
, str
, strtype
, k2d
);
367 ret
= i2d_X509_PUBKEY_bio(out
, xpk
);
369 /* Also frees |str| */
370 X509_PUBKEY_free(xpk
);
374 int ossl_prov_write_pub_pem_from_obj(BIO
*out
, const void *obj
, int obj_nid
,
375 int (*p2s
)(const void *obj
, int nid
,
378 int (*k2d
)(const void *obj
,
379 unsigned char **pder
))
383 int strtype
= V_ASN1_UNDEF
;
384 X509_PUBKEY
*xpk
= NULL
;
386 if (p2s
!= NULL
&& !p2s(obj
, obj_nid
, &str
, &strtype
))
389 xpk
= ossl_prov_pubkey_from_obj(obj
, obj_nid
, str
, strtype
, k2d
);
392 ret
= PEM_write_bio_X509_PUBKEY(out
, xpk
);
394 /* Also frees |str| */
395 X509_PUBKEY_free(xpk
);