#include "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
+#include "asn1_locl.h"
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
/* Minor tweak to operation: free up EVP_PKEY */
-static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it)
+static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
{
if (operation == ASN1_OP_FREE_POST)
{
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
{
- int ok=0;
- X509_PUBKEY *pk;
- X509_ALGOR *a;
- ASN1_OBJECT *o;
- unsigned char *s,*p = NULL;
- int i;
+ X509_PUBKEY *pk=NULL;
+ 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 ((a->parameter == NULL) ||
- (a->parameter->type != V_ASN1_NULL))
- {
- ASN1_TYPE_free(a->parameter);
- a->parameter=ASN1_TYPE_new();
- 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);
- i=i2d_DSAparams(dsa,NULL);
- if ((p=(unsigned char *)OPENSSL_malloc(i)) == NULL) goto err;
- pp=p;
- i2d_DSAparams(dsa,&pp);
- a->parameter=ASN1_TYPE_new();
- a->parameter->type=V_ASN1_SEQUENCE;
- a->parameter->value.sequence=ASN1_STRING_new();
- ASN1_STRING_set(a->parameter->value.sequence,p,i);
- OPENSSL_free(p);
- }
-#endif
-#ifndef OPENSSL_NO_EC
- else if (pkey->type == EVP_PKEY_EC)
+ if (meth)
{
- int nid=0;
- unsigned char *pp;
- EC_KEY *eckey;
-
- eckey = pkey->pkey.eckey;
- ASN1_TYPE_free(a->parameter);
-
- if ((a->parameter = ASN1_TYPE_new()) == NULL)
- {
- X509err(X509_F_X509_PUBKEY_SET, ERR_R_ASN1_LIB);
- goto err;
- }
-
- if (EC_GROUP_get_asn1_flag(eckey->group)
- && (nid = EC_GROUP_get_nid(eckey->group)))
+ if (meth->pub_encode)
{
- /* just set the OID */
- a->parameter->type = V_ASN1_OBJECT;
- a->parameter->value.object = OBJ_nid2obj(nid);
- }
- else /* explicit parameters */
- {
- if ((i = i2d_ECParameters(eckey, NULL)) == 0)
- {
- X509err(X509_F_X509_PUBKEY_SET, ERR_R_EC_LIB);
- goto err;
- }
- if ((p = (unsigned char *) OPENSSL_malloc(i)) == NULL)
+ if (!meth->pub_encode(pk, pkey))
{
- X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- pp = p;
- if (!i2d_ECParameters(eckey, &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;
+ X509err(X509_F_X509_PUBKEY_SET,
+ X509_R_PUBLIC_KEY_ENCODE_ERROR);
+ goto error;
}
- ASN1_STRING_set(a->parameter->value.sequence, p, i);
- OPENSSL_free(p);
+ }
+ else
+ {
+ 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;
+ goto error;
}
- p=s;
- i2d_PublicKey(pkey,&p);
- if (!M_ASN1_BIT_STRING_set(pk->public_key,s,i)) goto err;
- /* 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);
*x=pk;
- pk=NULL;
- ok=1;
-err:
+ return 1;
+error:
if (pk != NULL) X509_PUBKEY_free(pk);
- return(ok);
+ return 0;
}
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 (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE))
- {
- if ((ret->pkey.dsa = DSA_new()) == NULL)
- {
- X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- 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 (meth)
{
- if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE))
+ if (meth->pub_decode)
{
- /* type == V_ASN1_SEQUENCE => we have explicit parameters
- * (e.g. parameters in the X9_62_EC_PARAMETERS-structure )
- */
- if ((ret->pkey.eckey= 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.eckey, &cp, (long)j))
+ if (!meth->pub_decode(ret, key))
{
- X509err(X509_F_X509_PUBKEY_GET, ERR_R_EC_LIB);
- goto err;
+ X509err(X509_F_X509_PUBKEY_GET,
+ X509_R_PUBLIC_KEY_DECODE_ERROR);
+ goto error;
}
}
- else if (a->parameter && (a->parameter->type == V_ASN1_OBJECT))
+ else
{
- /* type == V_ASN1_OBJECT => the parameters are given
- * by an asn1 OID
- */
- EC_KEY *eckey;
- if (ret->pkey.eckey == NULL)
- ret->pkey.eckey = EC_KEY_new();
- eckey = ret->pkey.eckey;
- if (eckey->group)
- EC_GROUP_free(eckey->group);
- if ((eckey->group = EC_GROUP_new_by_nid(
- OBJ_obj2nid(a->parameter->value.object))) == NULL)
- goto err;
- EC_GROUP_set_asn1_flag(eckey->group,
- OPENSSL_EC_NAMED_CURVE);
+ X509err(X509_F_X509_PUBKEY_GET,
+ X509_R_METHOD_NOT_SUPPORTED);
+ goto error;
}
- /* 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);
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;
+ }