1/* crypto/asn1/x_pubkey.c */ 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59#include <stdio.h> 60#include "cryptlib.h" 61#include <openssl/asn1t.h> 62#include <openssl/x509.h> 63#ifndef OPENSSL_NO_RSA 64#include <openssl/rsa.h> 65#endif 66#ifndef OPENSSL_NO_DSA 67#include <openssl/dsa.h> 68#endif 69 70/* Minor tweak to operation: free up EVP_PKEY */ 71static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) 72 { 73 if (operation == ASN1_OP_FREE_POST) 74 { 75 X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; 76 EVP_PKEY_free(pubkey->pkey); 77 } 78 return 1; 79 } 80 81ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = { 82 ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), 83 ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING) 84} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY) 85 86IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY) 87 88int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) 89 { 90 X509_PUBKEY *pk=NULL; 91 X509_ALGOR *a; 92 ASN1_OBJECT *o; 93 unsigned char *s,*p = NULL; 94 int i; 95 96 if (x == NULL) return(0); 97 98 if ((pk=X509_PUBKEY_new()) == NULL) goto err; 99 a=pk->algor; 100 101 /* set the algorithm id */ 102 if ((o=OBJ_nid2obj(pkey->type)) == NULL) goto err; 103 ASN1_OBJECT_free(a->algorithm); 104 a->algorithm=o; 105 106 /* Set the parameter list */ 107 if (!pkey->save_parameters || (pkey->type == EVP_PKEY_RSA)) 108 { 109 if ((a->parameter == NULL) || 110 (a->parameter->type != V_ASN1_NULL)) 111 { 112 ASN1_TYPE_free(a->parameter); 113 if (!(a->parameter=ASN1_TYPE_new())) 114 { 115 X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE); 116 goto err; 117 } 118 a->parameter->type=V_ASN1_NULL; 119 } 120 } 121#ifndef OPENSSL_NO_DSA 122 else if (pkey->type == EVP_PKEY_DSA) 123 { 124 unsigned char *pp; 125 DSA *dsa; 126 127 dsa=pkey->pkey.dsa; 128 dsa->write_params=0; 129 ASN1_TYPE_free(a->parameter); 130 if ((i=i2d_DSAparams(dsa,NULL)) <= 0) 131 goto err; 132 if (!(p=(unsigned char *)OPENSSL_malloc(i))) 133 { 134 X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE); 135 goto err; 136 } 137 pp=p; 138 i2d_DSAparams(dsa,&pp); 139 if (!(a->parameter=ASN1_TYPE_new())) 140 { 141 OPENSSL_free(p); 142 X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE); 143 goto err; 144 } 145 a->parameter->type=V_ASN1_SEQUENCE; 146 if (!(a->parameter->value.sequence=ASN1_STRING_new())) 147 { 148 OPENSSL_free(p); 149 X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE); 150 goto err; 151 } 152 if (!ASN1_STRING_set(a->parameter->value.sequence,p,i)) 153 { 154 OPENSSL_free(p); 155 X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE); 156 goto err; 157 } 158 OPENSSL_free(p); 159 } 160#endif 161#ifndef OPENSSL_NO_EC 162 else if (pkey->type == EVP_PKEY_EC) 163 { 164 int nid=0; 165 unsigned char *pp; 166 EC_KEY *ec_key; 167 const EC_GROUP *group; 168 169 ec_key = pkey->pkey.ec; 170 ASN1_TYPE_free(a->parameter); 171 172 if ((a->parameter = ASN1_TYPE_new()) == NULL) 173 { 174 X509err(X509_F_X509_PUBKEY_SET, ERR_R_ASN1_LIB); 175 goto err; 176 } 177 178 group = EC_KEY_get0_group(ec_key); 179 if (EC_GROUP_get_asn1_flag(group) 180 && (nid = EC_GROUP_get_curve_name(group))) 181 { 182 /* just set the OID */ 183 a->parameter->type = V_ASN1_OBJECT; 184 a->parameter->value.object = OBJ_nid2obj(nid); 185 } 186 else /* explicit parameters */ 187 { 188 if ((i = i2d_ECParameters(ec_key, NULL)) == 0) 189 { 190 X509err(X509_F_X509_PUBKEY_SET, ERR_R_EC_LIB); 191 goto err; 192 } 193 if ((p = (unsigned char *) OPENSSL_malloc(i)) == NULL) 194 { 195 X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE); 196 goto err; 197 } 198 pp = p; 199 if (!i2d_ECParameters(ec_key, &pp)) 200 { 201 X509err(X509_F_X509_PUBKEY_SET, ERR_R_EC_LIB); 202 OPENSSL_free(p); 203 goto err; 204 } 205 a->parameter->type = V_ASN1_SEQUENCE; 206 if ((a->parameter->value.sequence = ASN1_STRING_new()) == NULL) 207 { 208 X509err(X509_F_X509_PUBKEY_SET, ERR_R_ASN1_LIB); 209 OPENSSL_free(p); 210 goto err; 211 } 212 ASN1_STRING_set(a->parameter->value.sequence, p, i); 213 OPENSSL_free(p); 214 } 215 } 216#endif 217 else if (1) 218 { 219 X509err(X509_F_X509_PUBKEY_SET,X509_R_UNSUPPORTED_ALGORITHM); 220 goto err; 221 } 222 223 if ((i=i2d_PublicKey(pkey,NULL)) <= 0) goto err; 224 if ((s=(unsigned char *)OPENSSL_malloc(i+1)) == NULL) 225 { 226 X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE); 227 goto err; 228 } 229 p=s; 230 i2d_PublicKey(pkey,&p); 231 if (!M_ASN1_BIT_STRING_set(pk->public_key,s,i)) 232 { 233 X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE); 234 goto err; 235 } 236 /* Set number of unused bits to zero */ 237 pk->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); 238 pk->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT; 239 240 OPENSSL_free(s); 241 242#if 0 243 CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY); 244 pk->pkey=pkey; 245#endif 246 247 if (*x != NULL) 248 X509_PUBKEY_free(*x); 249 250 *x=pk; 251 252 return 1; 253err: 254 if (pk != NULL) X509_PUBKEY_free(pk); 255 return 0; 256 } 257 258EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) 259 { 260 EVP_PKEY *ret=NULL; 261 long j; 262 int type; 263 const unsigned char *p; 264#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) 265 const unsigned char *cp; 266 X509_ALGOR *a; 267#endif 268 269 if (key == NULL) goto err; 270 271 if (key->pkey != NULL) 272 { 273 CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); 274 return(key->pkey); 275 } 276 277 if (key->public_key == NULL) goto err; 278 279 type=OBJ_obj2nid(key->algor->algorithm); 280 if ((ret = EVP_PKEY_new()) == NULL) 281 { 282 X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE); 283 goto err; 284 } 285 ret->type = EVP_PKEY_type(type); 286 287 /* the parameters must be extracted before the public key (ECDSA!) */ 288 289#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) 290 a=key->algor; 291#endif 292 293 if (0) 294 ; 295#ifndef OPENSSL_NO_DSA 296 else if (ret->type == EVP_PKEY_DSA) 297 { 298 if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE)) 299 { 300 if ((ret->pkey.dsa = DSA_new()) == NULL) 301 { 302 X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE); 303 goto err; 304 } 305 ret->pkey.dsa->write_params=0; 306 cp=p=a->parameter->value.sequence->data; 307 j=a->parameter->value.sequence->length; 308 if (!d2i_DSAparams(&ret->pkey.dsa, &cp, (long)j)) 309 goto err; 310 } 311 ret->save_parameters=1; 312 } 313#endif 314#ifndef OPENSSL_NO_EC 315 else if (ret->type == EVP_PKEY_EC) 316 { 317 if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE)) 318 { 319 /* type == V_ASN1_SEQUENCE => we have explicit parameters 320 * (e.g. parameters in the X9_62_EC_PARAMETERS-structure ) 321 */ 322 if ((ret->pkey.ec= EC_KEY_new()) == NULL) 323 { 324 X509err(X509_F_X509_PUBKEY_GET, 325 ERR_R_MALLOC_FAILURE); 326 goto err; 327 } 328 cp = p = a->parameter->value.sequence->data; 329 j = a->parameter->value.sequence->length; 330 if (!d2i_ECParameters(&ret->pkey.ec, &cp, (long)j)) 331 { 332 X509err(X509_F_X509_PUBKEY_GET, ERR_R_EC_LIB); 333 goto err; 334 } 335 } 336 else if (a->parameter && (a->parameter->type == V_ASN1_OBJECT)) 337 { 338 /* type == V_ASN1_OBJECT => the parameters are given 339 * by an asn1 OID 340 */ 341 EC_KEY *ec_key; 342 EC_GROUP *group; 343 344 if (ret->pkey.ec == NULL) 345 ret->pkey.ec = EC_KEY_new(); 346 ec_key = ret->pkey.ec; 347 if (ec_key == NULL) 348 goto err; 349 group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(a->parameter->value.object)); 350 if (group == NULL) 351 goto err; 352 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); 353 if (EC_KEY_set_group(ec_key, group) == 0) 354 goto err; 355 EC_GROUP_free(group); 356 } 357 /* the case implicitlyCA is currently not implemented */ 358 ret->save_parameters = 1; 359 } 360#endif 361 362 p=key->public_key->data; 363 j=key->public_key->length; 364 if (!d2i_PublicKey(type, &ret, &p, (long)j)) 365 { 366 X509err(X509_F_X509_PUBKEY_GET, X509_R_ERR_ASN1_LIB); 367 goto err; 368 } 369 370 key->pkey = ret; 371 CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY); 372 return(ret); 373err: 374 if (ret != NULL) 375 EVP_PKEY_free(ret); 376 return(NULL); 377 } 378 379/* Now two pseudo ASN1 routines that take an EVP_PKEY structure 380 * and encode or decode as X509_PUBKEY 381 */ 382 383EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, 384 long length) 385 { 386 X509_PUBKEY *xpk; 387 EVP_PKEY *pktmp; 388 xpk = d2i_X509_PUBKEY(NULL, pp, length); 389 if(!xpk) return NULL; 390 pktmp = X509_PUBKEY_get(xpk); 391 X509_PUBKEY_free(xpk); 392 if(!pktmp) return NULL; 393 if(a) 394 { 395 EVP_PKEY_free(*a); 396 *a = pktmp; 397 } 398 return pktmp; 399 } 400 401int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp) 402 { 403 X509_PUBKEY *xpk=NULL; 404 int ret; 405 if(!a) return 0; 406 if(!X509_PUBKEY_set(&xpk, a)) return 0; 407 ret = i2d_X509_PUBKEY(xpk, pp); 408 X509_PUBKEY_free(xpk); 409 return ret; 410 } 411 412/* The following are equivalents but which return RSA and DSA 413 * keys 414 */ 415#ifndef OPENSSL_NO_RSA 416RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, 417 long length) 418 { 419 EVP_PKEY *pkey; 420 RSA *key; 421 const unsigned char *q; 422 q = *pp; 423 pkey = d2i_PUBKEY(NULL, &q, length); 424 if (!pkey) return NULL; 425 key = EVP_PKEY_get1_RSA(pkey); 426 EVP_PKEY_free(pkey); 427 if (!key) return NULL; 428 *pp = q; 429 if (a) 430 { 431 RSA_free(*a); 432 *a = key; 433 } 434 return key; 435 } 436 437int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp) 438 { 439 EVP_PKEY *pktmp; 440 int ret; 441 if (!a) return 0; 442 pktmp = EVP_PKEY_new(); 443 if (!pktmp) 444 { 445 ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE); 446 return 0; 447 } 448 EVP_PKEY_set1_RSA(pktmp, a); 449 ret = i2d_PUBKEY(pktmp, pp); 450 EVP_PKEY_free(pktmp); 451 return ret; 452 } 453#endif 454 455#ifndef OPENSSL_NO_DSA 456DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, 457 long length) 458 { 459 EVP_PKEY *pkey; 460 DSA *key; 461 const unsigned char *q; 462 q = *pp; 463 pkey = d2i_PUBKEY(NULL, &q, length); 464 if (!pkey) return NULL; 465 key = EVP_PKEY_get1_DSA(pkey); 466 EVP_PKEY_free(pkey); 467 if (!key) return NULL; 468 *pp = q; 469 if (a) 470 { 471 DSA_free(*a); 472 *a = key; 473 } 474 return key; 475 } 476 477int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) 478 { 479 EVP_PKEY *pktmp; 480 int ret; 481 if(!a) return 0; 482 pktmp = EVP_PKEY_new(); 483 if(!pktmp) 484 { 485 ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE); 486 return 0; 487 } 488 EVP_PKEY_set1_DSA(pktmp, a); 489 ret = i2d_PUBKEY(pktmp, pp); 490 EVP_PKEY_free(pktmp); 491 return ret; 492 } 493#endif 494 495#ifndef OPENSSL_NO_EC 496EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length) 497 { 498 EVP_PKEY *pkey; 499 EC_KEY *key; 500 const unsigned char *q; 501 q = *pp; 502 pkey = d2i_PUBKEY(NULL, &q, length); 503 if (!pkey) return(NULL); 504 key = EVP_PKEY_get1_EC_KEY(pkey); 505 EVP_PKEY_free(pkey); 506 if (!key) return(NULL); 507 *pp = q; 508 if (a) 509 { 510 EC_KEY_free(*a); 511 *a = key; 512 } 513 return(key); 514 } 515 516int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp) 517 { 518 EVP_PKEY *pktmp; 519 int ret; 520 if (!a) return(0); 521 if ((pktmp = EVP_PKEY_new()) == NULL) 522 { 523 ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE); 524 return(0); 525 } 526 EVP_PKEY_set1_EC_KEY(pktmp, a); 527 ret = i2d_PUBKEY(pktmp, pp); 528 EVP_PKEY_free(pktmp); 529 return(ret); 530 } 531#endif 532