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