- EVP_PKEY *pkey;
- RSA *rsa;
- DSA *dsa;
- ASN1_INTEGER *dsapriv;
- X509_ALGOR *a;
- STACK *ndsa;
- BN_CTX *ctx;
- unsigned char *p;
- int plen, pkeylen;
- char obj_tmp[80];
-
- switch (p8->broken) {
- case PKCS8_OK:
- p = p8->pkey->value.octet_string->data;
- pkeylen = p8->pkey->value.octet_string->length;
- break;
-
- case PKCS8_NO_OCTET:
- p = p8->pkey->value.sequence->data;
- pkeylen = p8->pkey->value.sequence->length;
- break;
-
- default:
- EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE);
- return NULL;
- break;
- }
- if (!(pkey = EVP_PKEY_new())) {
- EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- a = p8->pkeyalg;
- switch (OBJ_obj2nid(a->algorithm))
- {
- case NID_rsaEncryption:
- if (!(rsa = d2i_RSAPrivateKey (NULL, &p, pkeylen))) {
- EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
- return NULL;
- }
- EVP_PKEY_assign_RSA (pkey, rsa);
- break;
-
- case NID_dsa:
- /* PKCS#8 DSA is weird: you just get a private key integer
- * and parameters in the AlgorithmIdentifier the pubkey must
- * be recalculated.
- */
-
- /* Check for broken Netscape Database DSA PKCS#8, UGH! */
- if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) {
- if(!(ndsa = ASN1_seq_unpack(p, pkeylen,
- (char *(*)())d2i_ASN1_INTEGER,
- ASN1_STRING_free))) {
- EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
- return NULL;
- }
- if(sk_num(ndsa) != 2 ) {
- EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
- sk_pop_free(ndsa, ASN1_STRING_free);
- return NULL;
- }
- dsapriv = (ASN1_INTEGER *) sk_pop(ndsa);
- sk_pop_free(ndsa, ASN1_STRING_free);
- } else if (!(dsapriv=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) {
- EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
- return NULL;
- }
- /* Retrieve parameters */
- if (a->parameter->type != V_ASN1_SEQUENCE) {
- EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_NO_DSA_PARAMETERS);
- return NULL;
- }
- p = a->parameter->value.sequence->data;
- plen = a->parameter->value.sequence->length;
- if (!(dsa = d2i_DSAparams (NULL, &p, plen))) {
- EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
- return NULL;
- }
- /* We have parameters now set private key */
- if (!(dsa->priv_key = ASN1_INTEGER_to_BN(dsapriv, NULL))) {
- EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR);
- DSA_free (dsa);
- return NULL;
- }
- /* Calculate public key (ouch!) */
- if (!(dsa->pub_key = BN_new())) {
- EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE);
- DSA_free (dsa);
- return NULL;
- }
- if (!(ctx = BN_CTX_new())) {
- EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE);
- DSA_free (dsa);
- return NULL;
- }
-
- if (!BN_mod_exp(dsa->pub_key, dsa->g,
- dsa->priv_key, dsa->p, ctx)) {
-
- EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_PUBKEY_ERROR);
- BN_CTX_free (ctx);
- DSA_free (dsa);
- return NULL;
- }
-
- EVP_PKEY_assign_DSA (pkey, dsa);
- BN_CTX_free (ctx);
- break;
+ EVP_PKEY *pkey = NULL;
+ ASN1_OBJECT *algoid;
+ char obj_tmp[80];
+
+ if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8))
+ return NULL;
+
+ if (!(pkey = EVP_PKEY_new())) {
+ EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) {
+ EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
+ i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
+ ERR_add_error_data(2, "TYPE=", obj_tmp);
+ goto error;
+ }
+
+ if (pkey->ameth->priv_decode) {
+ if (!pkey->ameth->priv_decode(pkey, p8)) {
+ EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_PRIVATE_KEY_DECODE_ERROR);
+ goto error;
+ }
+ } else {
+ EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_METHOD_NOT_SUPPORTED);
+ goto error;
+ }
+
+ return pkey;
+
+ error:
+ EVP_PKEY_free(pkey);
+ return NULL;
+}