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/ctype.h"
18 #include "crypto/ecx.h"
19 #include "prov/bio.h" /* ossl_prov_bio_printf() */
20 #include "prov/implementations.h"
21 #include "prov/providercommonerr.h" /* PROV_R_READ_KEY */
22 #include "serializer_local.h"
24 static PKCS8_PRIV_KEY_INFO
*
25 ossl_prov_p8info_from_obj(const void *obj
, int obj_nid
,
28 int (*k2d
)(const void *obj
,
29 unsigned char **pder
))
31 /* der, derlen store the key DER output and its length */
32 unsigned char *der
= NULL
;
34 /* The final PKCS#8 info */
35 PKCS8_PRIV_KEY_INFO
*p8info
= NULL
;
38 if ((p8info
= PKCS8_PRIV_KEY_INFO_new()) == NULL
39 || (derlen
= k2d(obj
, &der
)) <= 0
40 || !PKCS8_pkey_set0(p8info
, OBJ_nid2obj(obj_nid
), 0,
41 params_type
, params
, der
, derlen
)) {
42 ERR_raise(ERR_LIB_PROV
, ERR_R_MALLOC_FAILURE
);
43 PKCS8_PRIV_KEY_INFO_free(p8info
);
51 static X509_SIG
*ossl_prov_encp8_from_p8info(PKCS8_PRIV_KEY_INFO
*p8info
,
52 struct pkcs8_encrypt_ctx_st
*ctx
)
55 char buf
[PEM_BUFSIZE
];
56 const void *kstr
= ctx
->cipher_pass
;
57 size_t klen
= ctx
->cipher_pass_length
;
59 if (ctx
->cipher
== NULL
)
63 if (!ctx
->cb(buf
, sizeof(buf
), &klen
, NULL
, ctx
->cbarg
)) {
64 ERR_raise(ERR_LIB_PROV
, PROV_R_READ_KEY
);
69 /* NID == -1 means "standard" */
70 p8
= PKCS8_encrypt(-1, ctx
->cipher
, kstr
, klen
, NULL
, 0, 0, p8info
);
72 OPENSSL_cleanse(buf
, klen
);
76 static X509_SIG
*ossl_prov_encp8_from_obj(const void *obj
, int obj_nid
,
79 int (*k2d
)(const void *obj
,
80 unsigned char **pder
),
81 struct pkcs8_encrypt_ctx_st
*ctx
)
83 PKCS8_PRIV_KEY_INFO
*p8info
=
84 ossl_prov_p8info_from_obj(obj
, obj_nid
, params
, params_type
, k2d
);
85 X509_SIG
*p8
= ossl_prov_encp8_from_p8info(p8info
, ctx
);
87 PKCS8_PRIV_KEY_INFO_free(p8info
);
91 static X509_PUBKEY
*ossl_prov_pubkey_from_obj(const void *obj
, int obj_nid
,
94 int (*k2d
)(const void *obj
,
95 unsigned char **pder
))
97 /* der, derlen store the key DER output and its length */
98 unsigned char *der
= NULL
;
100 /* The final X509_PUBKEY */
101 X509_PUBKEY
*xpk
= NULL
;
104 if ((xpk
= X509_PUBKEY_new()) == NULL
105 || (derlen
= k2d(obj
, &der
)) <= 0
106 || !X509_PUBKEY_set0_param(xpk
, OBJ_nid2obj(obj_nid
),
107 params_type
, params
, der
, derlen
)) {
108 ERR_raise(ERR_LIB_PROV
, ERR_R_MALLOC_FAILURE
);
109 X509_PUBKEY_free(xpk
);
117 OSSL_FUNC_keymgmt_new_fn
*ossl_prov_get_keymgmt_new(const OSSL_DISPATCH
*fns
)
119 /* Pilfer the keymgmt dispatch table */
120 for (; fns
->function_id
!= 0; fns
++)
121 if (fns
->function_id
== OSSL_FUNC_KEYMGMT_NEW
)
122 return OSSL_FUNC_keymgmt_new(fns
);
127 OSSL_FUNC_keymgmt_free_fn
*ossl_prov_get_keymgmt_free(const OSSL_DISPATCH
*fns
)
129 /* Pilfer the keymgmt dispatch table */
130 for (; fns
->function_id
!= 0; fns
++)
131 if (fns
->function_id
== OSSL_FUNC_KEYMGMT_FREE
)
132 return OSSL_FUNC_keymgmt_free(fns
);
137 OSSL_FUNC_keymgmt_import_fn
*ossl_prov_get_keymgmt_import(const OSSL_DISPATCH
*fns
)
139 /* Pilfer the keymgmt dispatch table */
140 for (; fns
->function_id
!= 0; fns
++)
141 if (fns
->function_id
== OSSL_FUNC_KEYMGMT_IMPORT
)
142 return OSSL_FUNC_keymgmt_import(fns
);
147 OSSL_FUNC_keymgmt_export_fn
*ossl_prov_get_keymgmt_export(const OSSL_DISPATCH
*fns
)
149 /* Pilfer the keymgmt dispatch table */
150 for (; fns
->function_id
!= 0; fns
++)
151 if (fns
->function_id
== OSSL_FUNC_KEYMGMT_EXPORT
)
152 return OSSL_FUNC_keymgmt_export(fns
);
157 # ifdef SIXTY_FOUR_BIT_LONG
158 # define BN_FMTu "%lu"
159 # define BN_FMTx "%lx"
162 # ifdef SIXTY_FOUR_BIT
163 # define BN_FMTu "%llu"
164 # define BN_FMTx "%llx"
167 # ifdef THIRTY_TWO_BIT
168 # define BN_FMTu "%u"
169 # define BN_FMTx "%x"
172 int ossl_prov_print_labeled_bignum(BIO
*out
, const char *label
,
175 int ret
= 0, use_sep
= 0;
176 char *hex_str
= NULL
, *p
;
177 const char spaces
[] = " ";
178 const char *post_label_spc
= " ";
180 const char *neg
= "";
191 return BIO_printf(out
, "%s%s0\n", label
, post_label_spc
);
193 if (BN_num_bytes(bn
) <= BN_BYTES
) {
194 BN_ULONG
*words
= bn_get_words(bn
);
196 if (BN_is_negative(bn
))
199 return BIO_printf(out
, "%s%s%s" BN_FMTu
" (%s0x" BN_FMTx
")\n",
200 label
, post_label_spc
, neg
, words
[0], neg
, words
[0]);
203 hex_str
= BN_bn2hex(bn
);
209 if (BIO_printf(out
, "%s%s\n", label
, neg
) <= 0)
212 /* Keep track of how many bytes we have printed out so far */
215 if (BIO_printf(out
, "%s", spaces
) <= 0)
218 /* Add a leading 00 if the top bit is set */
220 if (BIO_printf(out
, "%02x", 0) <= 0)
226 /* Do a newline after every 15 hex bytes + add the space indent */
227 if ((bytes
% 15) == 0 && bytes
> 0) {
228 if (BIO_printf(out
, ":\n%s", spaces
) <= 0)
230 use_sep
= 0; /* The first byte on the next line doesnt have a : */
232 if (BIO_printf(out
, "%s%c%c", use_sep
? ":" : "",
233 ossl_tolower(p
[0]), ossl_tolower(p
[1])) <= 0)
239 if (BIO_printf(out
, "\n") <= 0)
243 OPENSSL_free(hex_str
);
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 (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 && BIO_printf(out
, "\n") <= 0)
262 if (BIO_printf(out
, " ") <= 0)
266 if (BIO_printf(out
, "%02x%s", buf
[i
],
267 (i
== buflen
- 1) ? "" : ":") <= 0)
270 if (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
);