#include "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.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)
-{
- if(operation == ASN1_OP_FREE_POST) {
+static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
+ {
+ if (operation == ASN1_OP_FREE_POST)
+ {
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
EVP_PKEY_free(pubkey->pkey);
- }
+ }
return 1;
-}
+ }
ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
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;
- 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 (meth)
{
- if ((a->parameter == NULL) ||
- (a->parameter->type != V_ASN1_NULL))
+ if (meth->pub_encode)
{
- ASN1_TYPE_free(a->parameter);
- a->parameter=ASN1_TYPE_new();
- a->parameter->type=V_ASN1_NULL;
+ if (!meth->pub_encode(pk, pkey))
+ {
+ X509err(X509_F_X509_PUBKEY_SET,
+ X509_R_PUBLIC_KEY_ENCODE_ERROR);
+ goto error;
+ }
+ }
+ else
+ {
+ X509err(X509_F_X509_PUBKEY_SET,
+ X509_R_METHOD_NOT_SUPPORTED);
+ goto error;
}
}
else
-#ifndef OPENSSL_NO_DSA
- 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);
- p=(unsigned char *)OPENSSL_malloc(i);
- 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);
- }
- else
-#endif
{
X509err(X509_F_X509_PUBKEY_SET,X509_R_UNSUPPORTED_ALGORITHM);
- goto err;
+ goto error;
}
- if ((i=i2d_PublicKey(pkey,NULL)) <= 0) goto err;
- if ((s=(unsigned char *)OPENSSL_malloc(i+1)) == NULL) goto err;
- 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;
- unsigned char *p;
-#ifndef OPENSSL_NO_DSA
- 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);
- }
+ {
+ CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+ return key->pkey;
+ }
- if (key->public_key == NULL) goto err;
+ if (key->public_key == NULL) goto error;
- type=OBJ_obj2nid(key->algor->algorithm);
- p=key->public_key->data;
- j=key->public_key->length;
- if ((ret=d2i_PublicKey(type,NULL,&p,(long)j)) == NULL)
+ if ((ret = EVP_PKEY_new()) == NULL)
{
- X509err(X509_F_X509_PUBKEY_GET,X509_R_ERR_ASN1_LIB);
- goto err;
+ X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE);
+ goto error;
}
- ret->save_parameters=0;
-#ifndef OPENSSL_NO_DSA
- a=key->algor;
- if (ret->type == EVP_PKEY_DSA)
+ meth = EVP_PKEY_ASN1_find(OBJ_obj2nid(key->algor->algorithm));
+
+ if (meth)
{
- if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE))
+ if (meth->pub_decode)
+ {
+ if (!meth->pub_decode(ret, key))
+ {
+ X509err(X509_F_X509_PUBKEY_GET,
+ X509_R_PUBLIC_KEY_DECODE_ERROR);
+ goto error;
+ }
+ }
+ else
{
- 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;
+ X509err(X509_F_X509_PUBKEY_GET,
+ X509_R_METHOD_NOT_SUPPORTED);
+ goto error;
}
- ret->save_parameters=1;
}
-#endif
- key->pkey=ret;
- CRYPTO_add(&ret->references,1,CRYPTO_LOCK_EVP_PKEY);
- return(ret);
-err:
+ else
+ {
+ 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;
+
+ error:
if (ret != NULL)
EVP_PKEY_free(ret);
return(NULL);
* and encode or decode as X509_PUBKEY
*/
-EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, unsigned char **pp,
+EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp,
long length)
-{
+ {
X509_PUBKEY *xpk;
EVP_PKEY *pktmp;
xpk = d2i_X509_PUBKEY(NULL, pp, length);
pktmp = X509_PUBKEY_get(xpk);
X509_PUBKEY_free(xpk);
if(!pktmp) return NULL;
- if(a) {
+ if(a)
+ {
EVP_PKEY_free(*a);
*a = pktmp;
- }
+ }
return pktmp;
-}
+ }
int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp)
-{
+ {
X509_PUBKEY *xpk=NULL;
int ret;
if(!a) return 0;
ret = i2d_X509_PUBKEY(xpk, pp);
X509_PUBKEY_free(xpk);
return ret;
-}
+ }
/* The following are equivalents but which return RSA and DSA
* keys
*/
#ifndef OPENSSL_NO_RSA
-RSA *d2i_RSA_PUBKEY(RSA **a, unsigned char **pp,
+RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp,
long length)
-{
+ {
EVP_PKEY *pkey;
RSA *key;
- unsigned char *q;
+ const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
- if(!pkey) return NULL;
+ if (!pkey) return NULL;
key = EVP_PKEY_get1_RSA(pkey);
EVP_PKEY_free(pkey);
- if(!key) return NULL;
+ if (!key) return NULL;
*pp = q;
- if(a) {
+ if (a)
+ {
RSA_free(*a);
*a = key;
- }
+ }
return key;
-}
+ }
int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp)
-{
+ {
EVP_PKEY *pktmp;
int ret;
- if(!a) return 0;
+ if (!a) return 0;
pktmp = EVP_PKEY_new();
- if(!pktmp) {
+ if (!pktmp)
+ {
ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE);
return 0;
- }
+ }
EVP_PKEY_set1_RSA(pktmp, a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return ret;
-}
+ }
#endif
#ifndef OPENSSL_NO_DSA
-DSA *d2i_DSA_PUBKEY(DSA **a, unsigned char **pp,
+DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp,
long length)
-{
+ {
EVP_PKEY *pkey;
DSA *key;
- unsigned char *q;
+ const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
- if(!pkey) return NULL;
+ if (!pkey) return NULL;
key = EVP_PKEY_get1_DSA(pkey);
EVP_PKEY_free(pkey);
- if(!key) return NULL;
+ if (!key) return NULL;
*pp = q;
- if(a) {
+ if (a)
+ {
DSA_free(*a);
*a = key;
- }
+ }
return key;
-}
+ }
int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
-{
+ {
EVP_PKEY *pktmp;
int ret;
if(!a) return 0;
pktmp = EVP_PKEY_new();
- if(!pktmp) {
+ if(!pktmp)
+ {
ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE);
return 0;
- }
+ }
EVP_PKEY_set1_DSA(pktmp, a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return ret;
-}
+ }
+#endif
+
+#ifndef OPENSSL_NO_EC
+EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
+ {
+ EVP_PKEY *pkey;
+ EC_KEY *key;
+ const unsigned char *q;
+ q = *pp;
+ pkey = d2i_PUBKEY(NULL, &q, length);
+ if (!pkey) return(NULL);
+ key = EVP_PKEY_get1_EC_KEY(pkey);
+ EVP_PKEY_free(pkey);
+ if (!key) return(NULL);
+ *pp = q;
+ if (a)
+ {
+ EC_KEY_free(*a);
+ *a = key;
+ }
+ return(key);
+ }
+
+int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp)
+ {
+ EVP_PKEY *pktmp;
+ int ret;
+ if (!a) return(0);
+ if ((pktmp = EVP_PKEY_new()) == NULL)
+ {
+ ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE);
+ return(0);
+ }
+ EVP_PKEY_set1_EC_KEY(pktmp, a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ EVP_PKEY_free(pktmp);
+ 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;
+ }