1 /* 2 * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 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 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include "internal/cryptlib.h" 13 #include <openssl/x509.h> 14 #include <openssl/rand.h> 15 #include <openssl/encoder.h> 16 #include <openssl/decoder.h> 17 #include "internal/provider.h" 18 #include "crypto/asn1.h" 19 #include "crypto/evp.h" 20 #include "crypto/x509.h" 21 22 /* Extract a private key from a PKCS8 structure */ 23 24 EVP_PKEY *evp_pkcs82pkey_legacy(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx, 25 const char *propq) 26 { 27 EVP_PKEY *pkey = NULL; 28 const ASN1_OBJECT *algoid; 29 char obj_tmp[80]; 30 31 if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8)) 32 return NULL; 33 34 if ((pkey = EVP_PKEY_new()) == NULL) { 35 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 36 return NULL; 37 } 38 39 if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) { 40 i2t_ASN1_OBJECT(obj_tmp, 80, algoid); 41 ERR_raise_data(ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM, 42 "TYPE=%s", obj_tmp); 43 goto error; 44 } 45 46 if (pkey->ameth->priv_decode_ex != NULL) { 47 if (!pkey->ameth->priv_decode_ex(pkey, p8, libctx, propq)) 48 goto error; 49 } else if (pkey->ameth->priv_decode != NULL) { 50 if (!pkey->ameth->priv_decode(pkey, p8)) { 51 ERR_raise(ERR_LIB_EVP, EVP_R_PRIVATE_KEY_DECODE_ERROR); 52 goto error; 53 } 54 } else { 55 ERR_raise(ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED); 56 goto error; 57 } 58 59 return pkey; 60 61 error: 62 EVP_PKEY_free(pkey); 63 return NULL; 64 } 65 66 EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx, 67 const char *propq) 68 { 69 EVP_PKEY *pkey = NULL; 70 const unsigned char *p8_data = NULL; 71 unsigned char *encoded_data = NULL; 72 int encoded_len; 73 int selection; 74 size_t len; 75 OSSL_DECODER_CTX *dctx = NULL; 76 77 if ((encoded_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &encoded_data)) <= 0 78 || encoded_data == NULL) 79 return NULL; 80 81 p8_data = encoded_data; 82 len = encoded_len; 83 selection = EVP_PKEY_KEYPAIR | EVP_PKEY_KEY_PARAMETERS; 84 dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", "PrivateKeyInfo", 85 NULL, selection, libctx, propq); 86 if (dctx == NULL 87 || !OSSL_DECODER_from_data(dctx, &p8_data, &len)) 88 /* try legacy */ 89 pkey = evp_pkcs82pkey_legacy(p8, libctx, propq); 90 91 OPENSSL_clear_free(encoded_data, encoded_len); 92 OSSL_DECODER_CTX_free(dctx); 93 return pkey; 94 } 95 96 EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8) 97 { 98 return EVP_PKCS82PKEY_ex(p8, NULL, NULL); 99 } 100 101 /* Turn a private key into a PKCS8 structure */ 102 103 PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(const EVP_PKEY *pkey) 104 { 105 PKCS8_PRIV_KEY_INFO *p8 = NULL; 106 OSSL_ENCODER_CTX *ctx = NULL; 107 108 /* 109 * The implementation for provider-native keys is to encode the 110 * key to a DER encoded PKCS#8 structure, then convert it to a 111 * PKCS8_PRIV_KEY_INFO with good old d2i functions. 112 */ 113 if (evp_pkey_is_provided(pkey)) { 114 int selection = OSSL_KEYMGMT_SELECT_ALL; 115 unsigned char *der = NULL; 116 size_t derlen = 0; 117 const unsigned char *pp; 118 119 if ((ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, 120 "DER", "PrivateKeyInfo", 121 NULL)) == NULL 122 || !OSSL_ENCODER_to_data(ctx, &der, &derlen)) 123 goto error; 124 125 pp = der; 126 p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &pp, (long)derlen); 127 OPENSSL_free(der); 128 if (p8 == NULL) 129 goto error; 130 } else { 131 p8 = PKCS8_PRIV_KEY_INFO_new(); 132 if (p8 == NULL) { 133 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 134 return NULL; 135 } 136 137 if (pkey->ameth != NULL) { 138 if (pkey->ameth->priv_encode != NULL) { 139 if (!pkey->ameth->priv_encode(p8, pkey)) { 140 ERR_raise(ERR_LIB_EVP, EVP_R_PRIVATE_KEY_ENCODE_ERROR); 141 goto error; 142 } 143 } else { 144 ERR_raise(ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED); 145 goto error; 146 } 147 } else { 148 ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); 149 goto error; 150 } 151 } 152 goto end; 153 error: 154 PKCS8_PRIV_KEY_INFO_free(p8); 155 p8 = NULL; 156 end: 157 OSSL_ENCODER_CTX_free(ctx); 158 return p8; 159 160 } 161 162 /* EVP_PKEY attribute functions */ 163 164 int EVP_PKEY_get_attr_count(const EVP_PKEY *key) 165 { 166 return X509at_get_attr_count(key->attributes); 167 } 168 169 int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos) 170 { 171 return X509at_get_attr_by_NID(key->attributes, nid, lastpos); 172 } 173 174 int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, const ASN1_OBJECT *obj, 175 int lastpos) 176 { 177 return X509at_get_attr_by_OBJ(key->attributes, obj, lastpos); 178 } 179 180 X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc) 181 { 182 return X509at_get_attr(key->attributes, loc); 183 } 184 185 X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc) 186 { 187 return X509at_delete_attr(key->attributes, loc); 188 } 189 190 int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr) 191 { 192 if (X509at_add1_attr(&key->attributes, attr)) 193 return 1; 194 return 0; 195 } 196 197 int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, 198 const ASN1_OBJECT *obj, int type, 199 const unsigned char *bytes, int len) 200 { 201 if (X509at_add1_attr_by_OBJ(&key->attributes, obj, type, bytes, len)) 202 return 1; 203 return 0; 204 } 205 206 int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, 207 int nid, int type, 208 const unsigned char *bytes, int len) 209 { 210 if (X509at_add1_attr_by_NID(&key->attributes, nid, type, bytes, len)) 211 return 1; 212 return 0; 213 } 214 215 int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, 216 const char *attrname, int type, 217 const unsigned char *bytes, int len) 218 { 219 if (X509at_add1_attr_by_txt(&key->attributes, attrname, type, bytes, len)) 220 return 1; 221 return 0; 222 } 223 224 const char *EVP_PKEY_get0_type_name(const EVP_PKEY *key) 225 { 226 const EVP_PKEY_ASN1_METHOD *ameth; 227 const char *name = NULL; 228 229 if (key->keymgmt != NULL) 230 return EVP_KEYMGMT_get0_name(key->keymgmt); 231 232 /* Otherwise fallback to legacy */ 233 ameth = EVP_PKEY_get0_asn1(key); 234 if (ameth != NULL) 235 EVP_PKEY_asn1_get0_info(NULL, NULL, 236 NULL, NULL, &name, ameth); 237 238 return name; 239 } 240 241 const OSSL_PROVIDER *EVP_PKEY_get0_provider(const EVP_PKEY *key) 242 { 243 if (evp_pkey_is_provided(key)) 244 return EVP_KEYMGMT_get0_provider(key->keymgmt); 245 return NULL; 246 } 247