]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
a28d06f3 | 2 | * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. |
cfcefcbe | 3 | * |
4a8b0c55 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
aa6bb135 RS |
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 | |
cfcefcbe DSH |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
11 | #include <stdlib.h> | |
b39fc560 | 12 | #include "internal/cryptlib.h" |
ec577822 BM |
13 | #include <openssl/x509.h> |
14 | #include <openssl/rand.h> | |
31a6b52f RL |
15 | #include <openssl/encoder.h> |
16 | #include "internal/provider.h" | |
25f2138b DMSP |
17 | #include "crypto/asn1.h" |
18 | #include "crypto/evp.h" | |
19 | #include "crypto/x509.h" | |
cfcefcbe DSH |
20 | |
21 | /* Extract a private key from a PKCS8 structure */ | |
22 | ||
b4250010 | 23 | EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx, |
d8652be0 | 24 | const char *propq) |
cfcefcbe | 25 | { |
0f113f3e | 26 | EVP_PKEY *pkey = NULL; |
245c6bc3 | 27 | const ASN1_OBJECT *algoid; |
0f113f3e MC |
28 | char obj_tmp[80]; |
29 | ||
30 | if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8)) | |
31 | return NULL; | |
32 | ||
75ebbd9a | 33 | if ((pkey = EVP_PKEY_new()) == NULL) { |
9311d0c4 | 34 | ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
35 | return NULL; |
36 | } | |
37 | ||
38 | if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) { | |
0f113f3e | 39 | i2t_ASN1_OBJECT(obj_tmp, 80, algoid); |
a150f8e1 RL |
40 | ERR_raise_data(ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM, |
41 | "TYPE=%s", obj_tmp); | |
0f113f3e MC |
42 | goto error; |
43 | } | |
44 | ||
d8652be0 MC |
45 | if (pkey->ameth->priv_decode_ex != NULL) { |
46 | if (!pkey->ameth->priv_decode_ex(pkey, p8, libctx, propq)) | |
472a88b7 | 47 | goto error; |
472a88b7 | 48 | } else if (pkey->ameth->priv_decode != NULL) { |
0f113f3e | 49 | if (!pkey->ameth->priv_decode(pkey, p8)) { |
9311d0c4 | 50 | ERR_raise(ERR_LIB_EVP, EVP_R_PRIVATE_KEY_DECODE_ERROR); |
0f113f3e MC |
51 | goto error; |
52 | } | |
53 | } else { | |
9311d0c4 | 54 | ERR_raise(ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED); |
0f113f3e MC |
55 | goto error; |
56 | } | |
57 | ||
58 | return pkey; | |
59 | ||
60 | error: | |
61 | EVP_PKEY_free(pkey); | |
62 | return NULL; | |
cfcefcbe DSH |
63 | } |
64 | ||
472a88b7 MC |
65 | EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8) |
66 | { | |
d8652be0 | 67 | return EVP_PKCS82PKEY_ex(p8, NULL, NULL); |
472a88b7 MC |
68 | } |
69 | ||
cfcefcbe DSH |
70 | /* Turn a private key into a PKCS8 structure */ |
71 | ||
9fdcc21f | 72 | PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(const EVP_PKEY *pkey) |
cfcefcbe | 73 | { |
31a6b52f RL |
74 | PKCS8_PRIV_KEY_INFO *p8 = NULL; |
75 | OSSL_ENCODER_CTX *ctx = NULL; | |
76 | ||
77 | /* | |
78 | * The implementation for provider-native keys is to encode the | |
79 | * key to a DER encoded PKCS#8 structure, then convert it to a | |
80 | * PKCS8_PRIV_KEY_INFO with good old d2i functions. | |
81 | */ | |
82 | if (evp_pkey_is_provided(pkey)) { | |
83 | int selection = OSSL_KEYMGMT_SELECT_ALL; | |
31a6b52f RL |
84 | unsigned char *der = NULL; |
85 | size_t derlen = 0; | |
86 | const unsigned char *pp; | |
87 | ||
fe75766c TM |
88 | if ((ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, |
89 | "DER", "pkcs8", | |
90 | NULL)) == NULL | |
31a6b52f RL |
91 | || !OSSL_ENCODER_to_data(ctx, &der, &derlen)) |
92 | goto error; | |
0f113f3e | 93 | |
31a6b52f RL |
94 | pp = der; |
95 | p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &pp, (long)derlen); | |
96 | OPENSSL_free(der); | |
97 | if (p8 == NULL) | |
98 | goto error; | |
99 | } else { | |
100 | p8 = PKCS8_PRIV_KEY_INFO_new(); | |
101 | if (p8 == NULL) { | |
9311d0c4 | 102 | ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); |
31a6b52f RL |
103 | return NULL; |
104 | } | |
b5275648 | 105 | |
31a6b52f RL |
106 | if (pkey->ameth != NULL) { |
107 | if (pkey->ameth->priv_encode != NULL) { | |
108 | if (!pkey->ameth->priv_encode(p8, pkey)) { | |
9311d0c4 | 109 | ERR_raise(ERR_LIB_EVP, EVP_R_PRIVATE_KEY_ENCODE_ERROR); |
31a6b52f RL |
110 | goto error; |
111 | } | |
112 | } else { | |
9311d0c4 | 113 | ERR_raise(ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED); |
0f113f3e MC |
114 | goto error; |
115 | } | |
116 | } else { | |
9311d0c4 | 117 | ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); |
0f113f3e MC |
118 | goto error; |
119 | } | |
0f113f3e | 120 | } |
31a6b52f | 121 | goto end; |
0f113f3e MC |
122 | error: |
123 | PKCS8_PRIV_KEY_INFO_free(p8); | |
31a6b52f RL |
124 | p8 = NULL; |
125 | end: | |
126 | OSSL_ENCODER_CTX_free(ctx); | |
127 | return p8; | |
128 | ||
cfcefcbe DSH |
129 | } |
130 | ||
b6995add DSH |
131 | /* EVP_PKEY attribute functions */ |
132 | ||
133 | int EVP_PKEY_get_attr_count(const EVP_PKEY *key) | |
134 | { | |
0f113f3e | 135 | return X509at_get_attr_count(key->attributes); |
b6995add DSH |
136 | } |
137 | ||
0f113f3e | 138 | int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos) |
b6995add | 139 | { |
0f113f3e | 140 | return X509at_get_attr_by_NID(key->attributes, nid, lastpos); |
b6995add DSH |
141 | } |
142 | ||
c47ba4e9 | 143 | int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, const ASN1_OBJECT *obj, |
0f113f3e | 144 | int lastpos) |
b6995add | 145 | { |
0f113f3e | 146 | return X509at_get_attr_by_OBJ(key->attributes, obj, lastpos); |
b6995add DSH |
147 | } |
148 | ||
149 | X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc) | |
150 | { | |
0f113f3e | 151 | return X509at_get_attr(key->attributes, loc); |
b6995add DSH |
152 | } |
153 | ||
154 | X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc) | |
155 | { | |
0f113f3e | 156 | return X509at_delete_attr(key->attributes, loc); |
b6995add DSH |
157 | } |
158 | ||
159 | int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr) | |
160 | { | |
0f113f3e MC |
161 | if (X509at_add1_attr(&key->attributes, attr)) |
162 | return 1; | |
163 | return 0; | |
b6995add DSH |
164 | } |
165 | ||
166 | int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, | |
0f113f3e MC |
167 | const ASN1_OBJECT *obj, int type, |
168 | const unsigned char *bytes, int len) | |
b6995add | 169 | { |
0f113f3e MC |
170 | if (X509at_add1_attr_by_OBJ(&key->attributes, obj, type, bytes, len)) |
171 | return 1; | |
172 | return 0; | |
b6995add DSH |
173 | } |
174 | ||
175 | int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, | |
0f113f3e MC |
176 | int nid, int type, |
177 | const unsigned char *bytes, int len) | |
b6995add | 178 | { |
0f113f3e MC |
179 | if (X509at_add1_attr_by_NID(&key->attributes, nid, type, bytes, len)) |
180 | return 1; | |
181 | return 0; | |
b6995add DSH |
182 | } |
183 | ||
184 | int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, | |
0f113f3e MC |
185 | const char *attrname, int type, |
186 | const unsigned char *bytes, int len) | |
b6995add | 187 | { |
0f113f3e MC |
188 | if (X509at_add1_attr_by_txt(&key->attributes, attrname, type, bytes, len)) |
189 | return 1; | |
190 | return 0; | |
b6995add | 191 | } |
d8025f4a MC |
192 | |
193 | const char *EVP_PKEY_get0_first_alg_name(const EVP_PKEY *key) | |
194 | { | |
195 | const EVP_PKEY_ASN1_METHOD *ameth; | |
196 | const char *name = NULL; | |
197 | ||
198 | if (key->keymgmt != NULL) | |
199 | return EVP_KEYMGMT_get0_first_name(key->keymgmt); | |
200 | ||
201 | /* Otherwise fallback to legacy */ | |
202 | ameth = EVP_PKEY_get0_asn1(key); | |
203 | if (ameth != NULL) | |
204 | EVP_PKEY_asn1_get0_info(NULL, NULL, | |
205 | NULL, NULL, &name, ameth); | |
206 | ||
207 | return name; | |
208 | } |