Initial support for pluggable public key ASN1 support. Process most public
authorDr. Stephen Henson <steve@openssl.org>
Mon, 20 Mar 2006 12:22:24 +0000 (12:22 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 20 Mar 2006 12:22:24 +0000 (12:22 +0000)
key ASN1 handling through a single EVP_PKEY_ASN1_METHOD structure and move
the spaghetti algorithm specific code to a single ASN1 module for each
algorithm.

24 files changed:
CHANGES
crypto/asn1/Makefile
crypto/asn1/ameth_lib.c [new file with mode: 0644]
crypto/asn1/asn1.h
crypto/asn1/p8_pkey.c
crypto/asn1/x_algor.c
crypto/asn1/x_pubkey.c
crypto/dsa/Makefile
crypto/dsa/dsa.h
crypto/dsa/dsa_ameth.c [new file with mode: 0644]
crypto/dsa/dsa_err.c
crypto/ec/Makefile
crypto/ec/ec.h
crypto/ec/ec_ameth.c [new file with mode: 0644]
crypto/evp/evp.h
crypto/evp/evp_err.c
crypto/evp/evp_pkey.c
crypto/ossl_typ.h
crypto/rsa/Makefile
crypto/rsa/rsa.h
crypto/rsa/rsa_ameth.c [new file with mode: 0644]
crypto/rsa/rsa_err.c
crypto/x509/x509.h
crypto/x509/x509_err.c

diff --git a/CHANGES b/CHANGES
index 41aae27..e054aed 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,14 @@
 
  Changes between 0.9.8a and 0.9.9  [xx XXX xxxx]
 
+  *) Initial support for pluggable public key ASN1.
+     De-spaghettify the public key ASN1 handling. Move public and private
+     key ASN1 handling to a new EVP_PKEY_ASN1_METHOD structure. Relocate
+     algorithm specific handling to a single module within the relevant
+     algorithm directory. Add functions to allow (near) opaque processing
+     of public and private key structures.
+     [Steve Henson]
+
   *) Implement the Supported Point Formats Extension for
      ECC ciphersuites from draft-ietf-tls-ecc-12.txt.
      [Douglas Stebila]
index efeec77..fe6a4be 100644 (file)
@@ -25,7 +25,7 @@ LIBSRC=       a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \
        x_nx509.c d2i_pu.c d2i_pr.c i2d_pu.c i2d_pr.c\
        t_req.c t_x509.c t_x509a.c t_crl.c t_pkey.c t_spki.c t_bitst.c \
        tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \
-       tasn_prn.c \
+       tasn_prn.c ameth_lib.c \
        f_int.c f_string.c n_pkey.c \
        f_enum.c x_pkey.c a_bool.c x_exten.c \
        asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_bytes.c a_strnid.c \
@@ -38,7 +38,7 @@ LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \
        x_nx509.o d2i_pu.o d2i_pr.o i2d_pu.o i2d_pr.o \
        t_req.o t_x509.o t_x509a.o t_crl.o t_pkey.o t_spki.o t_bitst.o \
        tasn_new.o tasn_fre.o tasn_enc.o tasn_dec.o tasn_utl.o tasn_typ.o \
-       tasn_prn.o \
+       tasn_prn.o ameth_lib.o \
        f_int.o f_string.o n_pkey.o \
        f_enum.o x_pkey.o a_bool.o x_exten.o \
        asn1_gen.o asn1_par.o asn1_lib.o asn1_err.o a_bytes.o a_strnid.o \
diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c
new file mode 100644 (file)
index 0000000..ddb6333
--- /dev/null
@@ -0,0 +1,113 @@
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include "cryptlib.h"
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+#include <openssl/ec.h>
+#include "asn1_locl.h"
+
+extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
+extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
+extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
+
+/* Keep this sorted in type order !! */
+const EVP_PKEY_ASN1_METHOD *standard_methods[] = 
+       {
+       &rsa_asn1_meths[0],
+       &rsa_asn1_meths[1],
+       &dsa_asn1_meths[0],
+       &dsa_asn1_meths[1],
+       &dsa_asn1_meths[2],
+       &dsa_asn1_meths[3],
+       &dsa_asn1_meths[4],
+       &eckey_asn1_meth
+       };
+
+#ifdef TEST
+void main()
+       {
+       int i;
+       for (i = 0;
+               i < sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
+               i++)
+               fprintf(stderr, "Number %d id=%d\n", i,
+                       standard_methods[i]->pkey_id);
+       }
+#endif
+
+static int ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a,
+                const EVP_PKEY_ASN1_METHOD * const *b)
+       {
+        return ((*a)->pkey_id - (*b)->pkey_id);
+       }
+
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_ASN1_find(int type)
+       {
+       EVP_PKEY_ASN1_METHOD tmp, *t = &tmp, **ret;
+       tmp.pkey_id = type;
+       ret = (EVP_PKEY_ASN1_METHOD **) OBJ_bsearch((char *)&t,
+                       (char *)standard_methods,
+                       sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *),
+                       sizeof(EVP_PKEY_ASN1_METHOD *),
+                       (int (*)(const void *, const void *))ameth_cmp);
+       if ((*ret)->pkey_flags & ASN1_PKEY_ALIAS)
+               return EVP_PKEY_ASN1_find((*ret)->pkey_base_id);
+       return *ret;
+       }
+
index 24fa436..32653eb 100644 (file)
@@ -282,6 +282,26 @@ typedef struct ASN1_TLC_st ASN1_TLC;
 /* This is just an opaque pointer */
 typedef struct ASN1_VALUE_st ASN1_VALUE;
 
+/* ASN1 public key method structure */
+
+#define ASN1_PKEY_ALIAS                0x1
+
+struct evp_pkey_asn1_method_st
+       {
+       int pkey_id;
+       int pkey_base_id;
+       unsigned long pkey_flags;
+       int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub);
+       int (*pub_encode)(X509_PUBKEY *pub, EVP_PKEY *pk);
+       int (*pub_print)(BIO *out, EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx);
+       int (*priv_decode)(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf);
+       int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pk);
+       int (*priv_print)(BIO *out, EVP_PKEY *pkey, int indent,
+                                                       ASN1_PCTX *pctx);
+       void (*pkey_free)(EVP_PKEY *pkey);
+       void (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2);
+       } /* EVP_PKEY_ASN1_METHOD */;
+
 /* Declare ASN1 functions: the implement macro in in asn1t.h */
 
 #define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type)
index 31ec2a8..e3b0a4d 100644 (file)
@@ -83,3 +83,73 @@ ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
 } ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
 
 IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+
+int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj,
+                                       int version,
+                                       int ptype, void *pval,
+                                       unsigned char *penc, int penclen)
+       {
+       unsigned char **ppenc = NULL;
+       if (version >= 0)
+               {
+               if (!ASN1_INTEGER_set(priv->version, version))
+                       return 0;
+               }
+       if (penc)
+               {
+               int pmtype;
+               ASN1_OCTET_STRING *oct;
+               oct = ASN1_OCTET_STRING_new();
+               if (!oct)
+                       return 0;
+               oct->data = penc;
+               ppenc = &oct->data;
+               oct->length = penclen;
+               if (priv->broken == PKCS8_NO_OCTET)
+                       pmtype = V_ASN1_SEQUENCE;
+               else
+                       pmtype = V_ASN1_OCTET_STRING;
+               ASN1_TYPE_set(priv->pkey, pmtype, oct);
+               }
+       if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval))
+               {
+               /* If call fails do not swallow 'enc' */
+               if (ppenc)
+                       *ppenc = NULL;
+               return 0;
+               }
+       return 1;
+       }
+
+int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg,
+               const unsigned char **pk, int *ppklen,
+               X509_ALGOR **pa,
+               PKCS8_PRIV_KEY_INFO *p8)
+       {
+       if (ppkalg)
+               *ppkalg = p8->pkeyalg->algorithm;
+       if(p8->pkey->type == V_ASN1_OCTET_STRING)
+               {
+               p8->broken = PKCS8_OK;
+               if (pk)
+                       {
+                       *pk = p8->pkey->value.octet_string->data;
+                       *ppklen = p8->pkey->value.octet_string->length;
+                       }
+               }
+       else if (p8->pkey->type == V_ASN1_SEQUENCE)
+               {
+               p8->broken = PKCS8_NO_OCTET;
+               if (pk)
+                       {
+                       *pk = p8->pkey->value.sequence->data;
+                       *ppklen = p8->pkey->value.sequence->length;
+                       }
+               }
+       else
+               return 0;
+       if (pa)
+               *pa = p8->pkeyalg;
+       return 1;
+       }
+
index 00b9ea5..63d40ce 100644 (file)
@@ -71,3 +71,55 @@ IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
 
 IMPLEMENT_STACK_OF(X509_ALGOR)
 IMPLEMENT_ASN1_SET_OF(X509_ALGOR)
+
+int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval)
+       {
+       if (!alg)
+               return 0;
+       if (ptype != V_ASN1_UNDEF)
+               {
+               if (alg->parameter == NULL)
+                       alg->parameter = ASN1_TYPE_new();
+               if (alg->parameter == NULL)
+                       return 0;
+               }
+       if (alg)
+               {
+               if (alg->algorithm)
+                       ASN1_OBJECT_free(alg->algorithm);
+               alg->algorithm = aobj;
+               }
+       if (ptype == 0)
+               return 1;       
+       if (ptype == V_ASN1_UNDEF)
+               {
+               if (alg->parameter)
+                       {
+                       ASN1_TYPE_free(alg->parameter);
+                       alg->parameter = NULL;
+                       }
+               }
+       else
+               ASN1_TYPE_set(alg->parameter, ptype, pval);
+       return 1;
+       }
+
+void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
+                                               X509_ALGOR *algor)
+       {
+       if (paobj)
+               *paobj = algor->algorithm;
+       if (*pptype)
+               {
+               if (algor->parameter == NULL)
+                       {
+                       *pptype = V_ASN1_UNDEF;
+                       return;
+                       }
+               else
+                       *pptype = algor->parameter->type;
+               if (ppval)
+                       *ppval = algor->parameter->value.ptr;
+               }
+       }
+
index 9ca6888..311e3bf 100644 (file)
@@ -89,161 +89,37 @@ IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
 int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
        {
        X509_PUBKEY *pk=NULL;
-       X509_ALGOR *a;
-       ASN1_OBJECT *o;
-       unsigned char *s,*p = NULL;
-       int i;
+       const EVP_PKEY_ASN1_METHOD *meth;
 
        if (x == NULL) return(0);
 
-       if ((pk=X509_PUBKEY_new()) == NULL) goto err;
-       a=pk->algor;
+       if ((pk=X509_PUBKEY_new()) == NULL) goto error;
 
-       /* set the algorithm id */
-       if ((o=OBJ_nid2obj(pkey->type)) == NULL) goto err;
-       ASN1_OBJECT_free(a->algorithm);
-       a->algorithm=o;
+       meth = EVP_PKEY_ASN1_find(pkey->type);
 
-       /* Set the parameter list */
-       if (!pkey->save_parameters || (pkey->type == EVP_PKEY_RSA))
+       if (meth)
                {
-               if ((a->parameter == NULL) ||
-                       (a->parameter->type != V_ASN1_NULL))
+               if (meth->pub_encode)
                        {
-                       ASN1_TYPE_free(a->parameter);
-                       if (!(a->parameter=ASN1_TYPE_new()))
+                       if (!meth->pub_encode(pk, pkey))
                                {
-                               X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
-                               goto err;
+                               X509err(X509_F_X509_PUBKEY_SET,
+                                       X509_R_PUBLIC_KEY_ENCODE_ERROR);
+                               goto error;
                                }
-                       a->parameter->type=V_ASN1_NULL;
                        }
-               }
-#ifndef OPENSSL_NO_DSA
-       else if (pkey->type == EVP_PKEY_DSA)
-               {
-               unsigned char *pp;
-               DSA *dsa;
-               
-               dsa=pkey->pkey.dsa;
-               dsa->write_params=0;
-               ASN1_TYPE_free(a->parameter);
-               if ((i=i2d_DSAparams(dsa,NULL)) <= 0)
-                       goto err;
-               if (!(p=(unsigned char *)OPENSSL_malloc(i)))
-                       {
-                       X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
-                       goto err;
-                       }
-               pp=p;
-               i2d_DSAparams(dsa,&pp);
-               if (!(a->parameter=ASN1_TYPE_new()))
-                       {
-                       OPENSSL_free(p);
-                       X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
-                       goto err;
-                       }
-               a->parameter->type=V_ASN1_SEQUENCE;
-               if (!(a->parameter->value.sequence=ASN1_STRING_new()))
-                       {
-                       OPENSSL_free(p);
-                       X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
-                       goto err;
-                       }
-               if (!ASN1_STRING_set(a->parameter->value.sequence,p,i))
-                       {
-                       OPENSSL_free(p);
-                       X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
-                       goto err;
-                       }
-               OPENSSL_free(p);
-               }
-#endif
-#ifndef OPENSSL_NO_EC
-       else if (pkey->type == EVP_PKEY_EC)
-               {
-               int nid=0;
-               unsigned char *pp;
-               EC_KEY *ec_key;
-               const EC_GROUP *group;
-               
-               ec_key = pkey->pkey.ec;
-               ASN1_TYPE_free(a->parameter);
-
-               if ((a->parameter = ASN1_TYPE_new()) == NULL)
-                       {
-                       X509err(X509_F_X509_PUBKEY_SET, ERR_R_ASN1_LIB);
-                       goto err;
-                       }
-
-               group = EC_KEY_get0_group(ec_key);
-               if (EC_GROUP_get_asn1_flag(group)
-                     && (nid = EC_GROUP_get_curve_name(group)))
+               else
                        {
-                       /* just set the OID */
-                       a->parameter->type = V_ASN1_OBJECT;
-                       a->parameter->value.object = OBJ_nid2obj(nid);
-                       }
-               else /* explicit parameters */
-                       {
-                       if ((i = i2d_ECParameters(ec_key, NULL)) == 0)
-                               {
-                               X509err(X509_F_X509_PUBKEY_SET, ERR_R_EC_LIB);
-                               goto err;
-                               }
-                       if ((p = (unsigned char *) OPENSSL_malloc(i)) == NULL)
-                               {
-                               X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE);
-                               goto err;
-                               }       
-                       pp = p;
-                       if (!i2d_ECParameters(ec_key, &pp))
-                               {
-                               X509err(X509_F_X509_PUBKEY_SET, ERR_R_EC_LIB);
-                               OPENSSL_free(p);
-                               goto err;
-                               }
-                       a->parameter->type = V_ASN1_SEQUENCE;
-                       if ((a->parameter->value.sequence = ASN1_STRING_new()) == NULL)
-                               {
-                               X509err(X509_F_X509_PUBKEY_SET, ERR_R_ASN1_LIB);
-                               OPENSSL_free(p);
-                               goto err;
-                               }
-                       ASN1_STRING_set(a->parameter->value.sequence, p, i);
-                       OPENSSL_free(p);
+                       X509err(X509_F_X509_PUBKEY_SET,
+                               X509_R_METHOD_NOT_SUPPORTED);
+                       goto error;
                        }
                }
-#endif
-       else if (1)
+       else
                {
                X509err(X509_F_X509_PUBKEY_SET,X509_R_UNSUPPORTED_ALGORITHM);
-               goto err;
-               }
-
-       if ((i=i2d_PublicKey(pkey,NULL)) <= 0) goto err;
-       if ((s=(unsigned char *)OPENSSL_malloc(i+1)) == NULL)
-               {
-               X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
-               goto err;
-               }
-       p=s;
-       i2d_PublicKey(pkey,&p);
-       if (!M_ASN1_BIT_STRING_set(pk->public_key,s,i))
-               {
-               X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
-               goto err;
+               goto error;
                }
-       /* Set number of unused bits to zero */
-       pk->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
-       pk->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT;
-
-       OPENSSL_free(s);
-
-#if 0
-       CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
-       pk->pkey=pkey;
-#endif
 
        if (*x != NULL)
                X509_PUBKEY_free(*x);
@@ -251,7 +127,7 @@ int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
        *x=pk;
 
        return 1;
-err:
+error:
        if (pk != NULL) X509_PUBKEY_free(pk);
        return 0;
        }
@@ -259,119 +135,56 @@ err:
 EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
        {
        EVP_PKEY *ret=NULL;
-       long j;
-       int type;
-       const unsigned char *p;
-#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA)
-       const unsigned char *cp;
-       X509_ALGOR *a;
-#endif
+       const EVP_PKEY_ASN1_METHOD *meth;
 
-       if (key == NULL) goto err;
+       if (key == NULL) goto error;
 
        if (key->pkey != NULL)
                {
                CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
-               return(key->pkey);
+               return key->pkey;
                }
 
-       if (key->public_key == NULL) goto err;
+       if (key->public_key == NULL) goto error;
 
-       type=OBJ_obj2nid(key->algor->algorithm);
        if ((ret = EVP_PKEY_new()) == NULL)
                {
                X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE);
-               goto err;
+               goto error;
                }
-       ret->type = EVP_PKEY_type(type);
 
-       /* the parameters must be extracted before the public key (ECDSA!) */
-       
-#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA)
-       a=key->algor;
-#endif
+       meth = EVP_PKEY_ASN1_find(OBJ_obj2nid(key->algor->algorithm));
 
-       if (0)
-               ;
-#ifndef OPENSSL_NO_DSA
-       else if (ret->type == EVP_PKEY_DSA)
+       if (meth)
                {
-               if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE))
+               if (meth->pub_decode)
                        {
-                       if ((ret->pkey.dsa = DSA_new()) == NULL)
+                       if (!meth->pub_decode(ret, key))
                                {
-                               X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE);
-                               goto err;
+                               X509err(X509_F_X509_PUBKEY_GET,
+                                               X509_R_PUBLIC_KEY_DECODE_ERROR);
+                               goto error;
                                }
-                       ret->pkey.dsa->write_params=0;
-                       cp=p=a->parameter->value.sequence->data;
-                       j=a->parameter->value.sequence->length;
-                       if (!d2i_DSAparams(&ret->pkey.dsa, &cp, (long)j))
-                               goto err;
                        }
-               ret->save_parameters=1;
-               }
-#endif
-#ifndef OPENSSL_NO_EC
-       else if (ret->type == EVP_PKEY_EC)
-               {
-               if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE))
+               else
                        {
-                       /* type == V_ASN1_SEQUENCE => we have explicit parameters
-                         * (e.g. parameters in the X9_62_EC_PARAMETERS-structure )
-                        */
-                       if ((ret->pkey.ec= EC_KEY_new()) == NULL)
-                               {
-                               X509err(X509_F_X509_PUBKEY_GET, 
-                                       ERR_R_MALLOC_FAILURE);
-                               goto err;
-                               }
-                       cp = p = a->parameter->value.sequence->data;
-                       j = a->parameter->value.sequence->length;
-                       if (!d2i_ECParameters(&ret->pkey.ec, &cp, (long)j))
-                               {
-                               X509err(X509_F_X509_PUBKEY_GET, ERR_R_EC_LIB);
-                               goto err;
-                               }
+                       X509err(X509_F_X509_PUBKEY_GET,
+                               X509_R_METHOD_NOT_SUPPORTED);
+                       goto error;
                        }
-               else if (a->parameter && (a->parameter->type == V_ASN1_OBJECT))
-                       {
-                       /* type == V_ASN1_OBJECT => the parameters are given
-                        * by an asn1 OID
-                        */
-                       EC_KEY   *ec_key;
-                       EC_GROUP *group;
-
-                       if (ret->pkey.ec == NULL)
-                               ret->pkey.ec = EC_KEY_new();
-                       ec_key = ret->pkey.ec;
-                       if (ec_key == NULL)
-                               goto err;
-                       group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(a->parameter->value.object));
-                       if (group == NULL)
-                               goto err;
-                       EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
-                       if (EC_KEY_set_group(ec_key, group) == 0)
-                               goto err;
-                       EC_GROUP_free(group);
-                       }
-                       /* the case implicitlyCA is currently not implemented */
-               ret->save_parameters = 1;
                }
-#endif
-
-       p=key->public_key->data;
-        j=key->public_key->length;
-        if (!d2i_PublicKey(type, &ret, &p, (long)j))
+       else
                {
-               X509err(X509_F_X509_PUBKEY_GET, X509_R_ERR_ASN1_LIB);
-               goto err;
+               X509err(X509_F_X509_PUBKEY_GET,X509_R_UNSUPPORTED_ALGORITHM);
+               goto error;
                }
 
        key->pkey = ret;
        CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY);
-       return(ret);
-err:
+
+       return ret;
+
+       error:
        if (ret != NULL)
                EVP_PKEY_free(ret);
        return(NULL);
@@ -530,3 +343,39 @@ int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp)
        return(ret);
        }
 #endif
+
+int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj,
+                                       int ptype, void *pval,
+                                       unsigned char *penc, int penclen)
+       {
+       if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
+               return 0;
+       if (penc)
+               {
+               if (pub->public_key->data)
+                       OPENSSL_free(pub->public_key->data);
+               pub->public_key->data = penc;
+               pub->public_key->length = penclen;
+               /* Set number of unused bits to zero */
+               pub->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+               pub->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT;
+               }
+       return 1;
+       }
+
+int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
+               const unsigned char **pk, int *ppklen,
+               X509_ALGOR **pa,
+               X509_PUBKEY *pub)
+       {
+       if (ppkalg)
+               *ppkalg = pub->algor->algorithm;
+       if (pk)
+               {
+               *pk = pub->public_key->data;
+               *ppklen = pub->public_key->length;
+               }
+       if (pa)
+               *pa = pub->algor;
+       return 1;
+       }
index 676baf7..483a5c3 100644 (file)
@@ -18,9 +18,9 @@ APPS=
 
 LIB=$(TOP)/libcrypto.a
 LIBSRC= dsa_gen.c dsa_key.c dsa_lib.c dsa_asn1.c dsa_vrf.c dsa_sign.c \
-       dsa_err.c dsa_ossl.c dsa_depr.c
+       dsa_err.c dsa_ossl.c dsa_depr.c dsa_ameth.c
 LIBOBJ= dsa_gen.o dsa_key.o dsa_lib.o dsa_asn1.o dsa_vrf.o dsa_sign.o \
-       dsa_err.o dsa_ossl.o dsa_depr.o
+       dsa_err.o dsa_ossl.o dsa_depr.o dsa_ameth.o
 
 SRC= $(LIBSRC)
 
index b12db98..5ee83e3 100644 (file)
@@ -262,6 +262,10 @@ void ERR_load_DSA_strings(void);
 #define DSA_F_DSA_NEW_METHOD                            103
 #define DSA_F_DSA_PRINT                                         104
 #define DSA_F_DSA_PRINT_FP                              105
+#define DSA_F_DSA_PRIV_DECODE                           115
+#define DSA_F_DSA_PRIV_ENCODE                           116
+#define DSA_F_DSA_PUB_DECODE                            117
+#define DSA_F_DSA_PUB_ENCODE                            118
 #define DSA_F_DSA_SIGN                                  106
 #define DSA_F_DSA_SIGN_SETUP                            107
 #define DSA_F_DSA_SIG_NEW                               109
@@ -270,8 +274,12 @@ void ERR_load_DSA_strings(void);
 #define DSA_F_SIG_CB                                    114
 
 /* Reason codes. */
+#define DSA_R_BN_DECODE_ERROR                           102
+#define DSA_R_BN_ERROR                                  103
 #define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE               100
+#define DSA_R_DECODE_ERROR                              104
 #define DSA_R_MISSING_PARAMETERS                        101
+#define DSA_R_PARAMETER_ENCODING_ERROR                  105
 
 #ifdef  __cplusplus
 }
diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c
new file mode 100644 (file)
index 0000000..8763eb9
--- /dev/null
@@ -0,0 +1,376 @@
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include "cryptlib.h"
+#include <openssl/x509.h>
+#include <openssl/asn1.h>
+#include <openssl/dsa.h>
+
+static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+       {
+       const unsigned char *p, *pm;
+       int pklen, pmlen;
+       int ptype;
+       void *pval;
+       ASN1_STRING *pstr;
+       X509_ALGOR *palg;
+       ASN1_INTEGER *public_key = NULL;
+
+       DSA *dsa = NULL;
+
+       if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
+               return 0;
+       X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+       if (ptype != V_ASN1_SEQUENCE)
+               {
+               DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_PARAMETER_ENCODING_ERROR);
+               goto err;
+               }
+
+       pstr = pval;    
+       pm = pstr->data;
+       pmlen = pstr->length;
+
+       if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen)))
+               {
+               DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
+               goto err;
+               }
+
+       if (!(public_key=d2i_ASN1_INTEGER(NULL, &p, pklen)))
+               {
+               DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
+               goto err;
+               }
+
+       /* We have parameters now set public key */
+       if (!(dsa->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)))
+               {
+               DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_BN_DECODE_ERROR);
+               goto err;
+               }
+
+       ASN1_INTEGER_free(public_key);
+
+       return 1;
+
+       err:
+       if (pubkey)
+               ASN1_INTEGER_free(public_key);
+       if (dsa)
+               DSA_free(dsa);
+       return 0;
+
+       }
+
+static int dsa_pub_encode(X509_PUBKEY *pk, EVP_PKEY *pkey)
+       {
+       DSA *dsa;
+       void *pval;
+       int ptype;
+       unsigned char *penc = NULL;
+       int penclen;
+
+       dsa=pkey->pkey.dsa;
+       if (pkey->save_parameters)
+               {
+               ASN1_STRING *str;
+               str = ASN1_STRING_new();
+               str->length = i2d_DSAparams(dsa, &str->data);
+               if (str->length <= 0)
+                       {
+                       DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+                       goto err;
+                       }
+               ptype = V_ASN1_SEQUENCE;
+               }
+       else
+               {
+               ptype = V_ASN1_UNDEF;
+               pval = NULL;
+               }
+       dsa->write_params=0;
+
+       penclen = i2d_DSAPublicKey(dsa, &penc);
+
+       if (penclen <= 0)
+               {
+               DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
+
+       if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DSA),
+                               ptype, pval, penc, penclen))
+               return 1;
+
+       err:
+       if (penc)
+               OPENSSL_free(penc);
+       if (pval)
+               ASN1_STRING_free(pval);
+
+       return 0;
+       }
+
+/* In PKCS#8 DSA: you just get a private key integer and parameters in the
+ * AlgorithmIdentifier the pubkey must be recalculated.
+ */
+       
+static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
+       {
+       const unsigned char *p, *pm;
+       int pklen, pmlen;
+       int ptype;
+       void *pval;
+       ASN1_STRING *pstr;
+       X509_ALGOR *palg;
+       ASN1_INTEGER *privkey = NULL;
+       BN_CTX *ctx = NULL;
+
+       STACK_OF(ASN1_TYPE) *ndsa = NULL;
+       DSA *dsa = NULL;
+
+       if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
+               return 0;
+       X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+       /* Check for broken DSA PKCS#8, UGH! */
+       if (*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED))
+               {
+               ASN1_TYPE *t1, *t2;
+               if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pklen, 
+                                                         d2i_ASN1_TYPE,
+                                                         ASN1_TYPE_free)))
+                       goto decerr;
+               if (sk_ASN1_TYPE_num(ndsa) != 2)
+                       goto decerr;
+               /* Handle Two broken types:
+                * SEQUENCE {parameters, priv_key}
+                * SEQUENCE {pub_key, priv_key}
+                */
+
+               t1 = sk_ASN1_TYPE_value(ndsa, 0);
+               t2 = sk_ASN1_TYPE_value(ndsa, 1);
+               if (t1->type == V_ASN1_SEQUENCE)
+                       {
+                       p8->broken = PKCS8_EMBEDDED_PARAM;
+                       pval = t1->value.ptr;
+                       }
+               else if (ptype == V_ASN1_SEQUENCE)
+                       p8->broken = PKCS8_NS_DB;
+               else
+                       goto decerr;
+
+               if (t2->type != V_ASN1_INTEGER)
+                       goto decerr;
+
+               privkey = t2->value.integer;
+               }
+       else
+               {
+               if (!(privkey=d2i_ASN1_INTEGER(NULL, &p, pklen)))
+                       goto decerr;
+               if (ptype != V_ASN1_SEQUENCE)
+                       goto decerr;
+               }
+
+       pstr = pval;    
+       pm = pstr->data;
+       pmlen = pstr->length;
+       if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen)))
+               goto decerr;
+       /* We have parameters now set private key */
+       if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL)))
+               {
+               DSAerr(DSA_F_DSA_PRIV_DECODE,DSA_R_BN_ERROR);
+               goto dsaerr;
+               }
+       /* Calculate public key */
+       if (!(dsa->pub_key = BN_new()))
+               {
+               DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
+               goto dsaerr;
+               }
+       if (!(ctx = BN_CTX_new()))
+               {
+               DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
+               goto dsaerr;
+               }
+                       
+       if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx))
+               {
+               DSAerr(DSA_F_DSA_PRIV_DECODE,DSA_R_BN_ERROR);
+               goto dsaerr;
+               }
+
+       EVP_PKEY_assign_DSA(pkey, dsa);
+       BN_CTX_free (ctx);
+       if(ndsa)
+               sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
+       else
+               ASN1_INTEGER_free(privkey);
+
+       return 1;
+
+       decerr:
+       DSAerr(DSA_F_DSA_PRIV_DECODE, EVP_R_DECODE_ERROR);
+       dsaerr:
+       BN_CTX_free (ctx);
+       sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
+       DSA_free(dsa);
+       EVP_PKEY_free(pkey);
+       return 0;
+       }
+
+static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
+{
+       ASN1_STRING *params = NULL;
+       ASN1_INTEGER *prkey = NULL;
+       unsigned char *dp = NULL;
+       int dplen;
+
+       params = ASN1_STRING_new();
+
+       if (!params)
+               {
+               DSAerr(DSA_F_DSA_PRIV_ENCODE,ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
+
+       params->length = i2d_DSAparams(pkey->pkey.dsa, &params->data);
+       if (params->length <= 0)
+               {
+               DSAerr(DSA_F_DSA_PRIV_ENCODE,ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
+       params->type = V_ASN1_SEQUENCE;
+
+       /* Get private key into integer */
+       prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL);
+
+       if (!prkey)
+               {
+               DSAerr(DSA_F_DSA_PRIV_ENCODE,DSA_R_BN_ERROR);
+               goto err;
+               }
+
+       dplen = i2d_ASN1_INTEGER(prkey, &dp);
+
+       ASN1_INTEGER_free(prkey);
+
+       if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dsa), 0,
+                               V_ASN1_SEQUENCE, params, dp, dplen))
+               goto err;
+
+       return 1;
+
+err:
+       if (dp != NULL)
+               OPENSSL_free(dp);
+       if (params != NULL)
+               ASN1_STRING_free(params);
+       if (prkey != NULL)
+               ASN1_INTEGER_free(prkey);
+       return 0;
+}
+
+/* NB these are sorted in pkey_id order, lowest first */
+
+const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] = 
+       {
+
+               {
+               EVP_PKEY_DSA2,
+               EVP_PKEY_DSA,
+               ASN1_PKEY_ALIAS
+               },
+
+               {
+               EVP_PKEY_DSA1,
+               EVP_PKEY_DSA,
+               ASN1_PKEY_ALIAS
+               },
+
+               {
+               EVP_PKEY_DSA4,
+               EVP_PKEY_DSA,
+               ASN1_PKEY_ALIAS
+               },
+
+               {
+               EVP_PKEY_DSA3,
+               EVP_PKEY_DSA,
+               ASN1_PKEY_ALIAS
+               },
+
+               {
+               EVP_PKEY_DSA,
+               EVP_PKEY_DSA,
+               0,
+               dsa_pub_decode,
+               dsa_pub_encode,
+               0,
+               dsa_priv_decode,
+               dsa_priv_encode,
+               0,
+               0,
+               0
+               }
+       };
+
index fd42053..920cabf 100644 (file)
@@ -78,6 +78,10 @@ static ERR_STRING_DATA DSA_str_functs[]=
 {ERR_FUNC(DSA_F_DSA_NEW_METHOD),       "DSA_new_method"},
 {ERR_FUNC(DSA_F_DSA_PRINT),    "DSA_print"},
 {ERR_FUNC(DSA_F_DSA_PRINT_FP), "DSA_print_fp"},
+{ERR_FUNC(DSA_F_DSA_PRIV_DECODE),      "DSA_PRIV_DECODE"},
+{ERR_FUNC(DSA_F_DSA_PRIV_ENCODE),      "DSA_PRIV_ENCODE"},
+{ERR_FUNC(DSA_F_DSA_PUB_DECODE),       "DSA_PUB_DECODE"},
+{ERR_FUNC(DSA_F_DSA_PUB_ENCODE),       "DSA_PUB_ENCODE"},
 {ERR_FUNC(DSA_F_DSA_SIGN),     "DSA_sign"},
 {ERR_FUNC(DSA_F_DSA_SIGN_SETUP),       "DSA_sign_setup"},
 {ERR_FUNC(DSA_F_DSA_SIG_NEW),  "DSA_SIG_new"},
@@ -89,8 +93,12 @@ static ERR_STRING_DATA DSA_str_functs[]=
 
 static ERR_STRING_DATA DSA_str_reasons[]=
        {
+{ERR_REASON(DSA_R_BN_DECODE_ERROR)       ,"bn decode error"},
+{ERR_REASON(DSA_R_BN_ERROR)              ,"bn error"},
 {ERR_REASON(DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE),"data too large for key size"},
+{ERR_REASON(DSA_R_DECODE_ERROR)          ,"decode error"},
 {ERR_REASON(DSA_R_MISSING_PARAMETERS)    ,"missing parameters"},
+{ERR_REASON(DSA_R_PARAMETER_ENCODING_ERROR),"parameter encoding error"},
 {0,NULL}
        };
 
index 9dbe99b..4a1622e 100644 (file)
@@ -19,11 +19,11 @@ APPS=
 LIB=$(TOP)/libcrypto.a
 LIBSRC=        ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c\
        ec_err.c ec_curve.c ec_check.c ec_print.c ec_asn1.c ec_key.c\
-       ec2_smpl.c ec2_mult.c
+       ec2_smpl.c ec2_mult.c ec_ameth.c
 
 LIBOBJ=        ec_lib.o ecp_smpl.o ecp_mont.o ecp_nist.o ec_cvt.o ec_mult.o\
        ec_err.o ec_curve.o ec_check.o ec_print.o ec_asn1.o ec_key.o\
-       ec2_smpl.o ec2_mult.o
+       ec2_smpl.o ec2_mult.o ec_ameth.o
 
 SRC= $(LIBSRC)
 
index 1ee6363..a5ec630 100644 (file)
@@ -918,6 +918,12 @@ void ERR_load_EC_strings(void);
 #define EC_F_D2I_ECPARAMETERS                           144
 #define EC_F_D2I_ECPKPARAMETERS                                 145
 #define EC_F_D2I_ECPRIVATEKEY                           146
+#define EC_F_ECKEY_PARAM2TYPE                           211
+#define EC_F_ECKEY_PRIV_DECODE                          212
+#define EC_F_ECKEY_PRIV_ENCODE                          213
+#define EC_F_ECKEY_PUB_DECODE                           214
+#define EC_F_ECKEY_PUB_ENCODE                           215
+#define EC_F_ECKEY_TYPE2PARAM                           216
 #define EC_F_ECPARAMETERS_PRINT                                 147
 #define EC_F_ECPARAMETERS_PRINT_FP                      148
 #define EC_F_ECPKPARAMETERS_PRINT                       149
@@ -1027,6 +1033,7 @@ void ERR_load_EC_strings(void);
 #define EC_R_ASN1_UNKNOWN_FIELD                                 116
 #define EC_R_BUFFER_TOO_SMALL                           100
 #define EC_R_D2I_ECPKPARAMETERS_FAILURE                         117
+#define EC_R_DECODE_ERROR                               137
 #define EC_R_DISCRIMINANT_IS_ZERO                       118
 #define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE               119
 #define EC_R_GROUP2PKPARAMETERS_FAILURE                         120
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
new file mode 100644 (file)
index 0000000..11aa432
--- /dev/null
@@ -0,0 +1,360 @@
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include "cryptlib.h"
+#include <openssl/x509.h>
+#include <openssl/ec.h>
+
+static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
+       {
+       const EC_GROUP  *group;
+       int nid;
+       if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) 
+       {
+               ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
+               return 0;
+       }
+       if (EC_GROUP_get_asn1_flag(group)
+                     && (nid = EC_GROUP_get_curve_name(group)))
+               /* we have a 'named curve' => just set the OID */
+               {
+               *ppval = OBJ_nid2obj(nid);
+               *pptype = V_ASN1_OBJECT;
+               }
+       else    /* explicit parameters */
+               {
+               ASN1_STRING *pstr = NULL;
+               pstr = ASN1_STRING_new();
+               if (!pstr)
+                       return 0;
+               pstr->length = i2d_ECParameters(ec_key, &pstr->data);
+               if (pstr->length < 0)
+                       {
+                       ASN1_STRING_free(pstr);
+                       ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB);
+                       return 0;
+                       }
+               *ppval = pstr;
+               *pptype = V_ASN1_SEQUENCE;
+               }
+       return 1;
+       }
+
+static int eckey_pub_encode(X509_PUBKEY *pk, EVP_PKEY *pkey)
+       {
+       EC_KEY *ec_key = pkey->pkey.ec;
+       void *pval = NULL;
+       int ptype;
+       unsigned char *penc = NULL, *p;
+       int penclen;
+
+       if (!eckey_param2type(&ptype, &pval, ec_key))
+               {
+               ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB);
+               return 0;
+               }
+       penclen = i2o_ECPublicKey(ec_key, NULL);
+       if (penclen <= 0)
+               goto err;
+       penc = OPENSSL_malloc(penclen);
+       if (!penc)
+               goto err;
+       p = penc;
+       penclen = i2o_ECPublicKey(ec_key, &p);
+       if (penclen <= 0)
+               goto err;
+       if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DSA),
+                               ptype, pval, penc, penclen))
+               return 1;
+       err:
+       if (ptype == V_ASN1_OBJECT)
+               ASN1_OBJECT_free(pval);
+       else
+               ASN1_STRING_free(pval);
+       if (penc)
+               OPENSSL_free(penc);
+       return 0;
+       }
+
+static EC_KEY *eckey_type2param(int ptype, void *pval)
+       {
+       EC_KEY *eckey = NULL;
+       if (ptype == V_ASN1_SEQUENCE)
+               {
+               ASN1_STRING *pstr = pval;
+               const unsigned char *pm = NULL;
+               int pmlen;
+               pm = pstr->data;
+               pmlen = pstr->length;
+               if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen)))
+                       {
+                       ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
+                       goto ecerr;
+                       }
+               }
+       else if (ptype == V_ASN1_OBJECT)
+               {
+               ASN1_OBJECT *poid = pval;
+               EC_GROUP *group;
+
+               /* type == V_ASN1_OBJECT => the parameters are given
+                * by an asn1 OID
+                */
+               if ((eckey = EC_KEY_new()) == NULL)
+                       {
+                       ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE);
+                       goto ecerr;
+                       }
+               group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
+               if (group == NULL)
+                       goto ecerr;
+               EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+               if (EC_KEY_set_group(eckey, group) == 0)
+                       goto ecerr;
+               EC_GROUP_free(group);
+               }
+       else
+               {
+               ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
+               goto ecerr;
+               }
+
+       return eckey;
+
+       ecerr:
+       if (eckey)
+               EC_KEY_free(eckey);
+       return NULL;
+       }
+
+static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+       {
+       const unsigned char *p = NULL;
+       void *pval;
+       int ptype, pklen;
+       EC_KEY *eckey = NULL;
+       X509_ALGOR *palg;
+
+       if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
+               return 0;
+       X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+       eckey = eckey_type2param(ptype, pval);
+
+       if (!eckey)
+               {
+               ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
+               return 0;
+               }
+
+       /* We have parameters now set public key */
+       if (!o2i_ECPublicKey(&eckey, &p, pklen))
+               {
+               ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR);
+               goto ecerr;
+               }
+
+       EVP_PKEY_assign_EC_KEY(pkey, eckey);
+       return 1;
+
+       ecerr:
+       if (eckey)
+               EC_KEY_free(eckey);
+       return 0;
+       }
+
+static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
+       {
+       const unsigned char *p = NULL;
+       void *pval;
+       int ptype, pklen;
+       EC_KEY *eckey = NULL;
+       X509_ALGOR *palg;
+
+       if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
+               return 0;
+       X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+       eckey = eckey_type2param(ptype, pval);
+
+       if (!eckey)
+               goto ecliberr;
+
+       /* We have parameters now set private key */
+       if (!d2i_ECPrivateKey(&eckey, &p, pklen))
+               {
+               ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
+               goto ecerr;
+               }
+
+       /* calculate public key (if necessary) */
+       if (EC_KEY_get0_public_key(eckey) == NULL)
+               {
+               const BIGNUM *priv_key;
+               const EC_GROUP *group;
+               EC_POINT *pub_key;
+               /* the public key was not included in the SEC1 private
+                * key => calculate the public key */
+               group   = EC_KEY_get0_group(eckey);
+               pub_key = EC_POINT_new(group);
+               if (pub_key == NULL)
+                       {
+                       ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
+                       goto ecliberr;
+                       }
+               if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group)))
+                       {
+                       EC_POINT_free(pub_key);
+                       ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
+                       goto ecliberr;
+                       }
+               priv_key = EC_KEY_get0_private_key(eckey);
+               if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL))
+                       {
+                       EC_POINT_free(pub_key);
+                       ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
+                       goto ecliberr;
+                       }
+               if (EC_KEY_set_public_key(eckey, pub_key) == 0)
+                       {
+                       EC_POINT_free(pub_key);
+                       ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
+                       goto ecliberr;
+                       }
+               EC_POINT_free(pub_key);
+               }
+
+       EVP_PKEY_assign_EC_KEY(pkey, eckey);
+       return 1;
+
+       ecliberr:
+       ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
+       ecerr:
+       if (eckey)
+               EC_KEY_free(eckey);
+       return 0;
+       }
+
+static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
+{
+       EC_KEY          *ec_key;
+       unsigned char   *ep, *p;
+       int             eplen, ptype;
+       void            *pval;
+       unsigned int    tmp_flags, old_flags;
+
+       ec_key = pkey->pkey.ec;
+
+       if (!eckey_param2type(&ptype, &pval, ec_key))
+               {
+               ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR);
+               return 0;
+               }
+
+       /* set the private key */
+
+       /* do not include the parameters in the SEC1 private key
+        * see PKCS#11 12.11 */
+       old_flags = EC_KEY_get_enc_flags(ec_key);
+       tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
+       EC_KEY_set_enc_flags(ec_key, tmp_flags);
+       eplen = i2d_ECPrivateKey(ec_key, NULL);
+       if (!eplen)
+       {
+               EC_KEY_set_enc_flags(ec_key, old_flags);
+               ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
+               return 0;
+       }
+       ep = (unsigned char *) OPENSSL_malloc(eplen);
+       if (!ep)
+       {
+               EC_KEY_set_enc_flags(ec_key, old_flags);
+               ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+               return 0;
+       }
+       p = ep;
+       if (!i2d_ECPrivateKey(ec_key, &p))
+       {
+               EC_KEY_set_enc_flags(ec_key, old_flags);
+               OPENSSL_free(ep);
+               ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
+       }
+       /* restore old encoding flags */
+       EC_KEY_set_enc_flags(ec_key, old_flags);
+
+       if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
+                               ptype, pval, ep, eplen))
+               return 0;
+
+       return 1;
+}
+
+EVP_PKEY_ASN1_METHOD eckey_asn1_meth = 
+       {
+       EVP_PKEY_EC,
+       0,
+       0,
+       eckey_pub_decode,
+       eckey_pub_encode,
+       0,
+       eckey_priv_decode,
+       eckey_priv_encode,
+       0,
+       0,
+       0
+       };
index 3f90b17..a13acaf 100644 (file)
@@ -847,6 +847,8 @@ int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
                    EVP_PBE_KEYGEN *keygen);
 void EVP_PBE_cleanup(void);
 
+const EVP_PKEY_ASN1_METHOD *EVP_PKEY_ASN1_find(int type);
+
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
@@ -873,6 +875,7 @@ void ERR_load_EVP_strings(void);
 #define EVP_F_EVP_PBE_ALG_ADD                           115
 #define EVP_F_EVP_PBE_CIPHERINIT                        116
 #define EVP_F_EVP_PKCS82PKEY                            111
+#define EVP_F_EVP_PKCS82PKEY_BROKEN                     136
 #define EVP_F_EVP_PKEY2PKCS8_BROKEN                     113
 #define EVP_F_EVP_PKEY_COPY_PARAMETERS                  103
 #define EVP_F_EVP_PKEY_DECRYPT                          104
@@ -918,6 +921,7 @@ void ERR_load_EVP_strings(void);
 #define EVP_R_INVALID_KEY_LENGTH                        130
 #define EVP_R_IV_TOO_LARGE                              102
 #define EVP_R_KEYGEN_FAILURE                            120
+#define EVP_R_METHOD_NOT_SUPPORTED                      144
 #define EVP_R_MISSING_PARAMETERS                        103
 #define EVP_R_NO_CIPHER_SET                             131
 #define EVP_R_NO_DIGEST_SET                             139
@@ -925,6 +929,8 @@ void ERR_load_EVP_strings(void);
 #define EVP_R_NO_SIGN_FUNCTION_CONFIGURED               104
 #define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED             105
 #define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE                         117
+#define EVP_R_PRIVATE_KEY_DECODE_ERROR                  145
+#define EVP_R_PRIVATE_KEY_ENCODE_ERROR                  146
 #define EVP_R_PUBLIC_KEY_NOT_RSA                        106
 #define EVP_R_UNKNOWN_PBE_ALGORITHM                     121
 #define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS               135
index e854aad..c312074 100644 (file)
@@ -87,6 +87,7 @@ static ERR_STRING_DATA EVP_str_functs[]=
 {ERR_FUNC(EVP_F_EVP_PBE_ALG_ADD),      "EVP_PBE_alg_add"},
 {ERR_FUNC(EVP_F_EVP_PBE_CIPHERINIT),   "EVP_PBE_CipherInit"},
 {ERR_FUNC(EVP_F_EVP_PKCS82PKEY),       "EVP_PKCS82PKEY"},
+{ERR_FUNC(EVP_F_EVP_PKCS82PKEY_BROKEN),        "EVP_PKCS82PKEY_BROKEN"},
 {ERR_FUNC(EVP_F_EVP_PKEY2PKCS8_BROKEN),        "EVP_PKEY2PKCS8_broken"},
 {ERR_FUNC(EVP_F_EVP_PKEY_COPY_PARAMETERS),     "EVP_PKEY_copy_parameters"},
 {ERR_FUNC(EVP_F_EVP_PKEY_DECRYPT),     "EVP_PKEY_decrypt"},
@@ -135,6 +136,7 @@ static ERR_STRING_DATA EVP_str_reasons[]=
 {ERR_REASON(EVP_R_INVALID_KEY_LENGTH)    ,"invalid key length"},
 {ERR_REASON(EVP_R_IV_TOO_LARGE)          ,"iv too large"},
 {ERR_REASON(EVP_R_KEYGEN_FAILURE)        ,"keygen failure"},
+{ERR_REASON(EVP_R_METHOD_NOT_SUPPORTED)  ,"method not supported"},
 {ERR_REASON(EVP_R_MISSING_PARAMETERS)    ,"missing parameters"},
 {ERR_REASON(EVP_R_NO_CIPHER_SET)         ,"no cipher set"},
 {ERR_REASON(EVP_R_NO_DIGEST_SET)         ,"no digest set"},
@@ -142,6 +144,8 @@ static ERR_STRING_DATA EVP_str_reasons[]=
 {ERR_REASON(EVP_R_NO_SIGN_FUNCTION_CONFIGURED),"no sign function configured"},
 {ERR_REASON(EVP_R_NO_VERIFY_FUNCTION_CONFIGURED),"no verify function configured"},
 {ERR_REASON(EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE),"pkcs8 unknown broken type"},
+{ERR_REASON(EVP_R_PRIVATE_KEY_DECODE_ERROR),"private key decode error"},
+{ERR_REASON(EVP_R_PRIVATE_KEY_ENCODE_ERROR),"private key encode error"},
 {ERR_REASON(EVP_R_PUBLIC_KEY_NOT_RSA)    ,"public key not rsa"},
 {ERR_REASON(EVP_R_UNKNOWN_PBE_ALGORITHM) ,"unknown pbe algorithm"},
 {ERR_REASON(EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS),"unsuported number of rounds"},
index 2a02ab0..eea4705 100644 (file)
@@ -3,7 +3,7 @@
  * project 1999.
  */
 /* ====================================================================
- * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #endif
 #include <openssl/bn.h>
 
-#ifndef OPENSSL_NO_DSA
-static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8inf, EVP_PKEY *pkey);
-#endif
-#ifndef OPENSSL_NO_EC
-static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8inf, EVP_PKEY *pkey);
-#endif
+#include "../asn1/asn1_locl.h"
 
 /* Extract a private key from a PKCS8 structure */
 
 EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8)
 {
        EVP_PKEY *pkey = NULL;
-#ifndef OPENSSL_NO_RSA
-       RSA *rsa = NULL;
-#endif
-#ifndef OPENSSL_NO_DSA
-       DSA *dsa = NULL;
-       ASN1_TYPE *t1, *t2;
-       ASN1_INTEGER *privkey;
-       STACK_OF(ASN1_TYPE) *ndsa = NULL;
-#endif
-#ifndef OPENSSL_NO_EC
-       EC_KEY *eckey = NULL;
-       const unsigned char *p_tmp;
-#endif
-#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
-       ASN1_TYPE    *param = NULL;     
-       BN_CTX *ctx = NULL;
-       int plen;
-#endif
-       X509_ALGOR *a;
-       const unsigned char *p;
-       const unsigned char *cp;
-       int pkeylen;
-       int  nid;
+       ASN1_OBJECT *algoid;
+       const EVP_PKEY_ASN1_METHOD *meth;
        char obj_tmp[80];
 
-       if(p8->pkey->type == V_ASN1_OCTET_STRING) {
-               p8->broken = PKCS8_OK;
-               p = p8->pkey->value.octet_string->data;
-               pkeylen = p8->pkey->value.octet_string->length;
-       } else {
-               p8->broken = PKCS8_NO_OCTET;
-               p = p8->pkey->value.sequence->data;
-               pkeylen = p8->pkey->value.sequence->length;
-       }
+       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;
        }
-       a = p8->pkeyalg;
-       nid = OBJ_obj2nid(a->algorithm);
-       switch(nid)
-       {
-#ifndef OPENSSL_NO_RSA
-               case NID_rsaEncryption:
-               cp = p;
-               if (!(rsa = d2i_RSAPrivateKey (NULL,&cp, pkeylen))) {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
-                       return NULL;
-               }
-               EVP_PKEY_assign_RSA (pkey, rsa);
-               break;
-#endif
-#ifndef OPENSSL_NO_DSA
-               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 DSA PKCS#8, UGH! */
-               if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) {
-                   if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pkeylen, 
-                                                         d2i_ASN1_TYPE,
-                                                         ASN1_TYPE_free))) {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
-                       goto dsaerr;
-                   }
-                   if(sk_ASN1_TYPE_num(ndsa) != 2 ) {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
-                       goto dsaerr;
-                   }
-                   /* Handle Two broken types:
-                    * SEQUENCE {parameters, priv_key}
-                    * SEQUENCE {pub_key, priv_key}
-                    */
-
-                   t1 = sk_ASN1_TYPE_value(ndsa, 0);
-                   t2 = sk_ASN1_TYPE_value(ndsa, 1);
-                   if(t1->type == V_ASN1_SEQUENCE) {
-                       p8->broken = PKCS8_EMBEDDED_PARAM;
-                       param = t1;
-                   } else if(a->parameter->type == V_ASN1_SEQUENCE) {
-                       p8->broken = PKCS8_NS_DB;
-                       param = a->parameter;
-                   } else {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
-                       goto dsaerr;
-                   }
-
-                   if(t2->type != V_ASN1_INTEGER) {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
-                       goto dsaerr;
-                   }
-                   privkey = t2->value.integer;
-               } else {
-                       if (!(privkey=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) {
-                               EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
-                               goto dsaerr;
-                       }
-                       param = p8->pkeyalg->parameter;
-               }
-               if (!param || (param->type != V_ASN1_SEQUENCE)) {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
-                       goto dsaerr;
-               }
-               cp = p = param->value.sequence->data;
-               plen = param->value.sequence->length;
-               if (!(dsa = d2i_DSAparams (NULL, &cp, plen))) {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
-                       goto dsaerr;
-               }
-               /* We have parameters now set private key */
-               if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR);
-                       goto dsaerr;
-               }
-               /* Calculate public key (ouch!) */
-               if (!(dsa->pub_key = BN_new())) {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE);
-                       goto dsaerr;
-               }
-               if (!(ctx = BN_CTX_new())) {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE);
-                       goto dsaerr;
-               }
-                       
-               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);
-                       goto dsaerr;
-               }
-
-               EVP_PKEY_assign_DSA(pkey, dsa);
-               BN_CTX_free (ctx);
-               if(ndsa) sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
-               else ASN1_INTEGER_free(privkey);
-               break;
-               dsaerr:
-               BN_CTX_free (ctx);
-               sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
-               DSA_free(dsa);
-               EVP_PKEY_free(pkey);
-               return NULL;
-               break;
-#endif
-#ifndef OPENSSL_NO_EC
-               case NID_X9_62_id_ecPublicKey:
-               p_tmp = p;
-               /* extract the ec parameters */
-               param = p8->pkeyalg->parameter;
 
-               if (!param || ((param->type != V_ASN1_SEQUENCE) &&
-                   (param->type != V_ASN1_OBJECT)))
-               {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
-                       goto ecerr;
-               }
+       meth = EVP_PKEY_ASN1_find(OBJ_obj2nid(algoid));
 
-               if (param->type == V_ASN1_SEQUENCE)
+       if (meth)
                {
-                       cp = p = param->value.sequence->data;
-                       plen = param->value.sequence->length;
-
-                       if (!(eckey = d2i_ECParameters(NULL, &cp, plen)))
+               if (meth->priv_decode)
                        {
+                       if (!meth->priv_decode(pkey, p8))
+                               {
                                EVPerr(EVP_F_EVP_PKCS82PKEY,
-                                       EVP_R_DECODE_ERROR);
-                               goto ecerr;
+                                       EVP_R_PRIVATE_KEY_DECODE_ERROR);
+                               goto error;
+                               }
                        }
-               }
                else
-               {
-                       EC_GROUP *group;
-                       cp = p = param->value.object->data;
-                       plen = param->value.object->length;
-
-                       /* type == V_ASN1_OBJECT => the parameters are given
-                        * by an asn1 OID
-                        */
-                       if ((eckey = EC_KEY_new()) == NULL)
                        {
-                               EVPerr(EVP_F_EVP_PKCS82PKEY,
-                                       ERR_R_MALLOC_FAILURE);
-                               goto ecerr;
+                       EVPerr(EVP_F_EVP_PKCS82PKEY,
+                                       EVP_R_METHOD_NOT_SUPPORTED);
+                       goto error;
                        }
-                       group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(a->parameter->value.object));
-                       if (group == NULL)
-                               goto ecerr;
-                       EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
-                       if (EC_KEY_set_group(eckey, group) == 0)
-                               goto ecerr;
-                       EC_GROUP_free(group);
-               }
-
-               /* We have parameters now set private key */
-               if (!d2i_ECPrivateKey(&eckey, &p_tmp, pkeylen))
-               {
-                       EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
-                       goto ecerr;
                }
-
-               /* calculate public key (if necessary) */
-               if (EC_KEY_get0_public_key(eckey) == NULL)
+       else
                {
-                       const BIGNUM *priv_key;
-                       const EC_GROUP *group;
-                       EC_POINT *pub_key;
-                       /* the public key was not included in the SEC1 private
-                        * key => calculate the public key */
-                       group   = EC_KEY_get0_group(eckey);
-                       pub_key = EC_POINT_new(group);
-                       if (pub_key == NULL)
-                       {
-                               EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
-                               goto ecerr;
-                       }
-                       if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group)))
-                       {
-                               EC_POINT_free(pub_key);
-                               EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
-                               goto ecerr;
-                       }
-                       priv_key = EC_KEY_get0_private_key(eckey);
-                       if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL))
-                       {
-                               EC_POINT_free(pub_key);
-                               EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
-                               goto ecerr;
-                       }
-                       if (EC_KEY_set_public_key(eckey, pub_key) == 0)
-                       {
-                               EC_POINT_free(pub_key);
-                               EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB);
-                               goto ecerr;
-                       }
-                       EC_POINT_free(pub_key);
-               }
-
-               EVP_PKEY_assign_EC_KEY(pkey, eckey);
-               break;
-ecerr:
-               if (eckey)
-                       EC_KEY_free(eckey);
-               if (pkey)
-                       EVP_PKEY_free(pkey);
-               return NULL;
-#endif
-               default:
                EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
-               if (!a->algorithm) BUF_strlcpy (obj_tmp, "NULL", sizeof obj_tmp);
-               else i2t_ASN1_OBJECT(obj_tmp, 80, a->algorithm);
+               i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
                ERR_add_error_data(2, "TYPE=", obj_tmp);
-               EVP_PKEY_free (pkey);
-               return NULL;
-       }
+               goto error;
+               }
        return pkey;
+
+       error:
+       EVP_PKEY_free (pkey);
+       return NULL;
 }
 
 PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey)
@@ -350,65 +132,46 @@ PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey)
 PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken)
 {
        PKCS8_PRIV_KEY_INFO *p8;
+       const EVP_PKEY_ASN1_METHOD *meth;
 
        if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) {        
                EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE);
                return NULL;
        }
        p8->broken = broken;
-       if (!ASN1_INTEGER_set(p8->version, 0)) {
-               EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE);
-               PKCS8_PRIV_KEY_INFO_free (p8);
-               return NULL;
-       }
-       if (!(p8->pkeyalg->parameter = ASN1_TYPE_new ())) {
-               EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE);
-               PKCS8_PRIV_KEY_INFO_free (p8);
-               return NULL;
-       }
-       p8->pkey->type = V_ASN1_OCTET_STRING;
-       switch (EVP_PKEY_type(pkey->type)) {
-#ifndef OPENSSL_NO_RSA
-               case EVP_PKEY_RSA:
 
-               if(p8->broken == PKCS8_NO_OCTET) p8->pkey->type = V_ASN1_SEQUENCE;
+       meth = EVP_PKEY_ASN1_find(pkey->type);
 
-               p8->pkeyalg->algorithm = OBJ_nid2obj(NID_rsaEncryption);
-               p8->pkeyalg->parameter->type = V_ASN1_NULL;
-               if (!ASN1_pack_string_of (EVP_PKEY,pkey, i2d_PrivateKey,
-                                        &p8->pkey->value.octet_string)) {
-                       EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,ERR_R_MALLOC_FAILURE);
-                       PKCS8_PRIV_KEY_INFO_free (p8);
-                       return NULL;
-               }
-               break;
-#endif
-#ifndef OPENSSL_NO_DSA
-               case EVP_PKEY_DSA:
-               if(!dsa_pkey2pkcs8(p8, pkey)) {
-                       PKCS8_PRIV_KEY_INFO_free (p8);
-                       return NULL;
+       if (meth)
+               {
+               if (meth->priv_encode)
+                       {
+                       if (!meth->priv_encode(p8, pkey))
+                               {
+                               EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,
+                                       EVP_R_PRIVATE_KEY_ENCODE_ERROR);
+                               goto error;
+                               }
+                       }
+               else
+                       {
+                       EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,
+                                       EVP_R_METHOD_NOT_SUPPORTED);
+                       goto error;
+                       }
                }
-
-               break;
-#endif
-#ifndef OPENSSL_NO_EC
-               case EVP_PKEY_EC:
-               if (!eckey_pkey2pkcs8(p8, pkey))
+       else
                {
-                       PKCS8_PRIV_KEY_INFO_free(p8);
-                       return(NULL);
+               EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN,
+                               EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
+               goto error;
                }
-               break;
-#endif
-               default:
-               EVPerr(EVP_F_EVP_PKEY2PKCS8_BROKEN, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
-               PKCS8_PRIV_KEY_INFO_free (p8);
-               return NULL;
-       }
        RAND_add(p8->pkey->value.octet_string->data,
                 p8->pkey->value.octet_string->length, 0.0);
        return p8;
+       error:
+       PKCS8_PRIV_KEY_INFO_free(p8);
+       return NULL;
 }
 
 PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken)
@@ -432,301 +195,6 @@ PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken)
        }
 }
 
-#ifndef OPENSSL_NO_DSA
-static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
-{
-       ASN1_STRING *params = NULL;
-       ASN1_INTEGER *prkey = NULL;
-       ASN1_TYPE *ttmp = NULL;
-       STACK_OF(ASN1_TYPE) *ndsa = NULL;
-       unsigned char *p = NULL, *q;
-       int len;
-
-       p8->pkeyalg->algorithm = OBJ_nid2obj(NID_dsa);
-       len = i2d_DSAparams (pkey->pkey.dsa, NULL);
-       if (!(p = OPENSSL_malloc(len))) {
-               EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-               goto err;
-       }
-       q = p;
-       i2d_DSAparams (pkey->pkey.dsa, &q);
-       if (!(params = ASN1_STRING_new())) {
-               EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-               goto err;
-       }
-       if (!ASN1_STRING_set(params, p, len)) {
-               EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-               goto err;
-       }
-       OPENSSL_free(p);
-       p = NULL;
-       /* Get private key into integer */
-       if (!(prkey = BN_to_ASN1_INTEGER (pkey->pkey.dsa->priv_key, NULL))) {
-               EVPerr(EVP_F_DSA_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
-               goto err;
-       }
-
-       switch(p8->broken) {
-
-               case PKCS8_OK:
-               case PKCS8_NO_OCTET:
-
-               if (!ASN1_pack_string_of(ASN1_INTEGER,prkey, i2d_ASN1_INTEGER,
-                                        &p8->pkey->value.octet_string)) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-
-               M_ASN1_INTEGER_free (prkey);
-               prkey = NULL;
-               p8->pkeyalg->parameter->value.sequence = params;
-               params = NULL;
-               p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE;
-
-               break;
-
-               case PKCS8_NS_DB:
-
-               p8->pkeyalg->parameter->value.sequence = params;
-               params = NULL;
-               p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE;
-               if (!(ndsa = sk_ASN1_TYPE_new_null())) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-               if (!(ttmp = ASN1_TYPE_new())) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-               if (!(ttmp->value.integer =
-                       BN_to_ASN1_INTEGER(pkey->pkey.dsa->pub_key, NULL))) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
-                       goto err;
-               }
-               ttmp->type = V_ASN1_INTEGER;
-               if (!sk_ASN1_TYPE_push(ndsa, ttmp)) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-
-               if (!(ttmp = ASN1_TYPE_new())) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-               ttmp->value.integer = prkey;
-               prkey = NULL;
-               ttmp->type = V_ASN1_INTEGER;
-               if (!sk_ASN1_TYPE_push(ndsa, ttmp)) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-               ttmp = NULL;
-
-               if (!(p8->pkey->value.octet_string = ASN1_OCTET_STRING_new())) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-
-               if (!ASN1_seq_pack_ASN1_TYPE(ndsa, i2d_ASN1_TYPE,
-                                        &p8->pkey->value.octet_string->data,
-                                        &p8->pkey->value.octet_string->length)) {
-
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-               sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
-               break;
-
-               case PKCS8_EMBEDDED_PARAM:
-
-               p8->pkeyalg->parameter->type = V_ASN1_NULL;
-               if (!(ndsa = sk_ASN1_TYPE_new_null())) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-               if (!(ttmp = ASN1_TYPE_new())) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-               ttmp->value.sequence = params;
-               params = NULL;
-               ttmp->type = V_ASN1_SEQUENCE;
-               if (!sk_ASN1_TYPE_push(ndsa, ttmp)) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-
-               if (!(ttmp = ASN1_TYPE_new())) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-               ttmp->value.integer = prkey;
-               prkey = NULL;
-               ttmp->type = V_ASN1_INTEGER;
-               if (!sk_ASN1_TYPE_push(ndsa, ttmp)) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-               ttmp = NULL;
-
-               if (!(p8->pkey->value.octet_string = ASN1_OCTET_STRING_new())) {
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-
-               if (!ASN1_seq_pack_ASN1_TYPE(ndsa, i2d_ASN1_TYPE,
-                                        &p8->pkey->value.octet_string->data,
-                                        &p8->pkey->value.octet_string->length)) {
-
-                       EVPerr(EVP_F_DSA_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
-                       goto err;
-               }
-               sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
-               break;
-       }
-       return 1;
-err:
-       if (p != NULL) OPENSSL_free(p);
-       if (params != NULL) ASN1_STRING_free(params);
-       if (prkey != NULL) M_ASN1_INTEGER_free(prkey);
-       if (ttmp != NULL) ASN1_TYPE_free(ttmp);
-       if (ndsa != NULL) sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
-       return 0;
-}
-#endif
-
-#ifndef OPENSSL_NO_EC
-static int eckey_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
-{
-       EC_KEY          *ec_key;
-       const EC_GROUP  *group;
-       unsigned char   *p, *pp;
-       int             nid, i, ret = 0;
-       unsigned int    tmp_flags, old_flags;
-
-       ec_key = pkey->pkey.ec;
-       if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) 
-       {
-               EVPerr(EVP_F_ECKEY_PKEY2PKCS8, EVP_R_MISSING_PARAMETERS);
-               return 0;
-       }
-
-       /* set the ec parameters OID */
-       if (p8->pkeyalg->algorithm)
-               ASN1_OBJECT_free(p8->pkeyalg->algorithm);
-
-       p8->pkeyalg->algorithm = OBJ_nid2obj(NID_X9_62_id_ecPublicKey);
-
-       /* set the ec parameters */
-
-       if (p8->pkeyalg->parameter)
-       {
-               ASN1_TYPE_free(p8->pkeyalg->parameter);
-               p8->pkeyalg->parameter = NULL;
-       }
-
-       if ((p8->pkeyalg->parameter = ASN1_TYPE_new()) == NULL)
-       {
-               EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
-               return 0;
-       }
-       
-       if (EC_GROUP_get_asn1_flag(group)
-                     && (nid = EC_GROUP_get_curve_name(group)))
-       {
-               /* we have a 'named curve' => just set the OID */
-               p8->pkeyalg->parameter->type = V_ASN1_OBJECT;
-               p8->pkeyalg->parameter->value.object = OBJ_nid2obj(nid);
-       }
-       else    /* explicit parameters */
-       {
-               if ((i = i2d_ECParameters(ec_key, NULL)) == 0)
-               {
-                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB);
-                       return 0;
-               }
-               if ((p = (unsigned char *) OPENSSL_malloc(i)) == NULL)
-               {
-                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
-                       return 0;
-               }       
-               pp = p;
-               if (!i2d_ECParameters(ec_key, &pp))
-               {
-                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB);
-                       OPENSSL_free(p);
-                       return 0;
-               }
-               p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE;
-               if ((p8->pkeyalg->parameter->value.sequence 
-                       = ASN1_STRING_new()) == NULL)
-               {
-                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_ASN1_LIB);
-                       OPENSSL_free(p);
-                       return 0;
-               }
-               ASN1_STRING_set(p8->pkeyalg->parameter->value.sequence, p, i);
-               OPENSSL_free(p);
-       }
-
-       /* set the private key */
-
-       /* do not include the parameters in the SEC1 private key
-        * see PKCS#11 12.11 */
-       old_flags = EC_KEY_get_enc_flags(pkey->pkey.ec);
-       tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
-       EC_KEY_set_enc_flags(pkey->pkey.ec, tmp_flags);
-       i = i2d_ECPrivateKey(pkey->pkey.ec, NULL);
-       if (!i)
-       {
-               EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags);
-               EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB);
-               return 0;
-       }
-       p = (unsigned char *) OPENSSL_malloc(i);
-       if (!p)
-       {
-               EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags);
-               EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
-               return 0;
-       }
-       pp = p;
-       if (!i2d_ECPrivateKey(pkey->pkey.ec, &pp))
-       {
-               EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags);
-               EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_EC_LIB);
-               OPENSSL_free(p);
-               return 0;
-       }
-       /* restore old encoding flags */
-       EC_KEY_set_enc_flags(pkey->pkey.ec, old_flags);
-
-       switch(p8->broken) {
-
-               case PKCS8_OK:
-               p8->pkey->value.octet_string = ASN1_OCTET_STRING_new();
-               if (!p8->pkey->value.octet_string ||
-                   !M_ASN1_OCTET_STRING_set(p8->pkey->value.octet_string,
-                   (const void *)p, i))
-
-               {
-                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8, ERR_R_MALLOC_FAILURE);
-               }
-               else
-                       ret = 1;
-               break;
-               case PKCS8_NO_OCTET:            /* RSA specific */
-               case PKCS8_NS_DB:               /* DSA specific */
-               case PKCS8_EMBEDDED_PARAM:      /* DSA specific */
-               default:
-                       EVPerr(EVP_F_ECKEY_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
-       }
-       OPENSSL_cleanse(p, (size_t)i);
-       OPENSSL_free(p);
-       return ret;
-}
-#endif
-
 /* EVP_PKEY attribute functions */
 
 int EVP_PKEY_get_attr_count(const EVP_PKEY *key)
index 336c8d2..ffb6244 100644 (file)
@@ -121,6 +121,8 @@ typedef struct env_md_st EVP_MD;
 typedef struct env_md_ctx_st EVP_MD_CTX;
 typedef struct evp_pkey_st EVP_PKEY;
 
+typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
+
 typedef struct dh_st DH;
 typedef struct dh_method DH_METHOD;
 
@@ -139,9 +141,12 @@ typedef struct x509_st X509;
 typedef struct X509_algor_st X509_ALGOR;
 typedef struct X509_crl_st X509_CRL;
 typedef struct X509_name_st X509_NAME;
+typedef struct X509_pubkey_st X509_PUBKEY;
 typedef struct x509_store_st X509_STORE;
 typedef struct x509_store_ctx_st X509_STORE_CTX;
 
+typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO;
+
 typedef struct v3_ext_ctx X509V3_CTX;
 typedef struct conf_st CONF;
 
index 1390081..71efa61 100644 (file)
@@ -19,10 +19,10 @@ APPS=
 LIB=$(TOP)/libcrypto.a
 LIBSRC= rsa_eay.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_saos.c rsa_err.c \
        rsa_pk1.c rsa_ssl.c rsa_none.c rsa_oaep.c rsa_chk.c rsa_null.c \
-       rsa_pss.c rsa_x931.c rsa_asn1.c rsa_depr.c
+       rsa_pss.c rsa_x931.c rsa_asn1.c rsa_depr.c rsa_ameth.c
 LIBOBJ= rsa_eay.o rsa_gen.o rsa_lib.o rsa_sign.o rsa_saos.o rsa_err.o \
        rsa_pk1.o rsa_ssl.o rsa_none.o rsa_oaep.o rsa_chk.o rsa_null.o \
-       rsa_pss.o rsa_x931.o rsa_asn1.o rsa_depr.o
+       rsa_pss.o rsa_x931.o rsa_asn1.o rsa_depr.o rsa_ameth.o
 
 SRC= $(LIBSRC)
 
index d302254..6a9062b 100644 (file)
@@ -374,6 +374,9 @@ void ERR_load_RSA_strings(void);
 #define RSA_F_RSA_PADDING_CHECK_X931                    128
 #define RSA_F_RSA_PRINT                                         115
 #define RSA_F_RSA_PRINT_FP                              116
+#define RSA_F_RSA_PRIV_DECODE                           137
+#define RSA_F_RSA_PRIV_ENCODE                           138
+#define RSA_F_RSA_PUB_DECODE                            139
 #define RSA_F_RSA_SETUP_BLINDING                        136
 #define RSA_F_RSA_SIGN                                  117
 #define RSA_F_RSA_SIGN_ASN1_OCTET_STRING                118
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
new file mode 100644 (file)
index 0000000..96e5375
--- /dev/null
@@ -0,0 +1,154 @@
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include "cryptlib.h"
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+#include <openssl/rsa.h>
+
+static int rsa_pub_encode(X509_PUBKEY *pk, EVP_PKEY *pkey)
+       {
+       unsigned char *penc = NULL;
+       int penclen;
+       penclen = i2d_RSAPublicKey(pkey->pkey.rsa, &penc);
+       if (penclen <= 0)
+               return 0;
+       if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_RSA),
+                               V_ASN1_NULL, NULL, penc, penclen))
+               return 1;
+
+       OPENSSL_free(penc);
+       return 0;
+       }
+
+static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+       {
+       const unsigned char *p;
+       int pklen;
+       RSA *rsa = NULL;
+       if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, NULL, pubkey))
+               return 0;
+       if (!(rsa = d2i_RSAPublicKey(NULL, &p, pklen)))
+               {
+               RSAerr(RSA_F_RSA_PUB_DECODE, ERR_R_RSA_LIB);
+               return 0;
+               }
+       EVP_PKEY_assign_RSA (pkey, rsa);
+       return 1;
+       }
+
+static int rsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
+       {
+       const unsigned char *p;
+       int pklen;
+       RSA *rsa = NULL;
+       if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8))
+               return 0;
+       if (!(rsa = d2i_RSAPrivateKey (NULL, &p, pklen)))
+               {
+               RSAerr(RSA_F_RSA_PRIV_DECODE, ERR_R_RSA_LIB);
+               return 0;
+               }
+       EVP_PKEY_assign_RSA (pkey, rsa);
+       return 1;
+       }
+
+static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
+       {
+       unsigned char *rk = NULL;
+       int rklen;
+       rklen = i2d_RSAPrivateKey(pkey->pkey.rsa, &rk);
+
+       if (rklen <= 0)
+               {
+               RSAerr(RSA_F_RSA_PRIV_ENCODE,ERR_R_MALLOC_FAILURE);
+               return 0;
+               }
+
+       if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_rsaEncryption), 0,
+                               V_ASN1_NULL, NULL, rk, rklen))
+               {
+               RSAerr(RSA_F_RSA_PRIV_ENCODE,ERR_R_MALLOC_FAILURE);
+               return 0;
+               }
+
+       return 1;
+       }
+
+const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] = 
+       {
+               {
+               EVP_PKEY_RSA,
+               EVP_PKEY_RSA,
+               0,
+               rsa_pub_decode,
+               rsa_pub_encode,
+               0,
+               rsa_priv_decode,
+               rsa_priv_encode,
+               0,
+               0,
+               0
+               },
+
+               {
+               EVP_PKEY_RSA2,
+               EVP_PKEY_RSA,
+               ASN1_PKEY_ALIAS
+               }
+       };
index cfb1e90..fc43065 100644 (file)
@@ -88,7 +88,7 @@ static ERR_STRING_DATA RSA_str_functs[]=
 {ERR_FUNC(RSA_F_RSA_NULL_PUBLIC_ENCRYPT),      "RSA_NULL_PUBLIC_ENCRYPT"},
 {ERR_FUNC(RSA_F_RSA_PADDING_ADD_NONE), "RSA_padding_add_none"},
 {ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP),   "RSA_padding_add_PKCS1_OAEP"},
-{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_PSS),    "RSA_PADDING_ADD_PKCS1_PSS"},
+{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_PSS),    "RSA_padding_add_PKCS1_PSS"},
 {ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1), "RSA_padding_add_PKCS1_type_1"},
 {ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2), "RSA_padding_add_PKCS1_type_2"},
 {ERR_FUNC(RSA_F_RSA_PADDING_ADD_SSLV23),       "RSA_padding_add_SSLv23"},
@@ -101,12 +101,15 @@ static ERR_STRING_DATA RSA_str_functs[]=
 {ERR_FUNC(RSA_F_RSA_PADDING_CHECK_X931),       "RSA_padding_check_X931"},
 {ERR_FUNC(RSA_F_RSA_PRINT),    "RSA_print"},
 {ERR_FUNC(RSA_F_RSA_PRINT_FP), "RSA_print_fp"},
+{ERR_FUNC(RSA_F_RSA_PRIV_DECODE),      "RSA_PRIV_DECODE"},
+{ERR_FUNC(RSA_F_RSA_PRIV_ENCODE),      "RSA_PRIV_ENCODE"},
+{ERR_FUNC(RSA_F_RSA_PUB_DECODE),       "RSA_PUB_DECODE"},
 {ERR_FUNC(RSA_F_RSA_SETUP_BLINDING),   "RSA_setup_blinding"},
 {ERR_FUNC(RSA_F_RSA_SIGN),     "RSA_sign"},
 {ERR_FUNC(RSA_F_RSA_SIGN_ASN1_OCTET_STRING),   "RSA_sign_ASN1_OCTET_STRING"},
 {ERR_FUNC(RSA_F_RSA_VERIFY),   "RSA_verify"},
 {ERR_FUNC(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING), "RSA_verify_ASN1_OCTET_STRING"},
-{ERR_FUNC(RSA_F_RSA_VERIFY_PKCS1_PSS), "RSA_VERIFY_PKCS1_PSS"},
+{ERR_FUNC(RSA_F_RSA_VERIFY_PKCS1_PSS), "RSA_verify_PKCS1_PSS"},
 {0,NULL}
        };
 
@@ -141,17 +144,17 @@ static ERR_STRING_DATA RSA_str_reasons[]=
 {ERR_REASON(RSA_R_NULL_BEFORE_BLOCK_MISSING),"null before block missing"},
 {ERR_REASON(RSA_R_N_DOES_NOT_EQUAL_P_Q)  ,"n does not equal p q"},
 {ERR_REASON(RSA_R_OAEP_DECODING_ERROR)   ,"oaep decoding error"},
-{ERR_REASON(RSA_R_SLEN_RECOVERY_FAILED)  ,"salt length recovery failed"},
 {ERR_REASON(RSA_R_PADDING_CHECK_FAILED)  ,"padding check failed"},
 {ERR_REASON(RSA_R_P_NOT_PRIME)           ,"p not prime"},
 {ERR_REASON(RSA_R_Q_NOT_PRIME)           ,"q not prime"},
 {ERR_REASON(RSA_R_RSA_OPERATIONS_NOT_SUPPORTED),"rsa operations not supported"},
+{ERR_REASON(RSA_R_SLEN_CHECK_FAILED)     ,"salt length check failed"},
+{ERR_REASON(RSA_R_SLEN_RECOVERY_FAILED)  ,"salt length recovery failed"},
 {ERR_REASON(RSA_R_SSLV3_ROLLBACK_ATTACK) ,"sslv3 rollback attack"},
 {ERR_REASON(RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD),"the asn1 object identifier is not known for this md"},
 {ERR_REASON(RSA_R_UNKNOWN_ALGORITHM_TYPE),"unknown algorithm type"},
 {ERR_REASON(RSA_R_UNKNOWN_PADDING_TYPE)  ,"unknown padding type"},
 {ERR_REASON(RSA_R_WRONG_SIGNATURE_LENGTH),"wrong signature length"},
-{ERR_REASON(RSA_R_SLEN_CHECK_FAILED)     ,"salt length check failed"},
 {0,NULL}
        };
 
index 37b17f1..c512ac6 100644 (file)
@@ -155,12 +155,12 @@ typedef struct X509_val_st
        ASN1_TIME *notAfter;
        } X509_VAL;
 
-typedef struct X509_pubkey_st
+struct X509_pubkey_st
        {
        X509_ALGOR *algor;
        ASN1_BIT_STRING *public_key;
        EVP_PKEY *pkey;
-       } X509_PUBKEY;
+       };
 
 typedef struct X509_sig_st
        {
@@ -545,7 +545,7 @@ X509_ALGOR *prf;
 
 /* PKCS#8 private key info structure */
 
-typedef struct pkcs8_priv_key_info_st
+struct pkcs8_priv_key_info_st
         {
         int broken;     /* Flag for various broken formats */
 #define PKCS8_OK               0
@@ -556,7 +556,7 @@ typedef struct pkcs8_priv_key_info_st
         X509_ALGOR *pkeyalg;
         ASN1_TYPE *pkey; /* Should be OCTET STRING but some are broken */
         STACK_OF(X509_ATTRIBUTE) *attributes;
-        } PKCS8_PRIV_KEY_INFO;
+        };
 
 #ifdef  __cplusplus
 }
@@ -859,6 +859,10 @@ X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex);
 X509_CRL *X509_CRL_dup(X509_CRL *crl);
 X509_REQ *X509_REQ_dup(X509_REQ *req);
 X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn);
+int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval);
+void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
+                                               X509_ALGOR *algor);
+
 X509_NAME *X509_NAME_dup(X509_NAME *xn);
 X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
 
@@ -1244,6 +1248,22 @@ PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey);
 PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken);
 PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken);
 
+int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj,
+                       int version, int ptype, void *pval,
+                               unsigned char *penc, int penclen);
+int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg,
+               const unsigned char **pk, int *ppklen,
+               X509_ALGOR **pa,
+               PKCS8_PRIV_KEY_INFO *p8);
+
+int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj,
+                                       int ptype, void *pval,
+                                       unsigned char *penc, int penclen);
+int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
+               const unsigned char **pk, int *ppklen,
+               X509_ALGOR **pa,
+               X509_PUBKEY *pub);
+
 int X509_check_trust(X509 *x, int id, int flags);
 int X509_TRUST_get_count(void);
 X509_TRUST * X509_TRUST_get0(int idx);
@@ -1323,7 +1343,10 @@ void ERR_load_X509_strings(void);
 #define X509_R_KEY_VALUES_MISMATCH                      116
 #define X509_R_LOADING_CERT_DIR                                 103
 #define X509_R_LOADING_DEFAULTS                                 104
+#define X509_R_METHOD_NOT_SUPPORTED                     124
 #define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY             105
+#define X509_R_PUBLIC_KEY_DECODE_ERROR                  125
+#define X509_R_PUBLIC_KEY_ENCODE_ERROR                  126
 #define X509_R_SHOULD_RETRY                             106
 #define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN       107
 #define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY           108
index b7bc383..b6b5926 100644 (file)
@@ -132,7 +132,10 @@ static ERR_STRING_DATA X509_str_reasons[]=
 {ERR_REASON(X509_R_KEY_VALUES_MISMATCH)  ,"key values mismatch"},
 {ERR_REASON(X509_R_LOADING_CERT_DIR)     ,"loading cert dir"},
 {ERR_REASON(X509_R_LOADING_DEFAULTS)     ,"loading defaults"},
+{ERR_REASON(X509_R_METHOD_NOT_SUPPORTED) ,"method not supported"},
 {ERR_REASON(X509_R_NO_CERT_SET_FOR_US_TO_VERIFY),"no cert set for us to verify"},
+{ERR_REASON(X509_R_PUBLIC_KEY_DECODE_ERROR),"public key decode error"},
+{ERR_REASON(X509_R_PUBLIC_KEY_ENCODE_ERROR),"public key encode error"},
 {ERR_REASON(X509_R_SHOULD_RETRY)         ,"should retry"},
 {ERR_REASON(X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN),"unable to find parameters in chain"},
 {ERR_REASON(X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY),"unable to get certs public key"},