x_pubkey.c revision 237657
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 /* Check to see if another thread set key->pkey first */ 371 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); 372 if (key->pkey) 373 { 374 EVP_PKEY_free(ret); 375 ret = key->pkey; 376 } 377 else 378 key->pkey = ret; 379 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); 380 CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY); 381 return(ret); 382err: 383 if (ret != NULL) 384 EVP_PKEY_free(ret); 385 return(NULL); 386 } 387 388/* Now two pseudo ASN1 routines that take an EVP_PKEY structure 389 * and encode or decode as X509_PUBKEY 390 */ 391 392EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, 393 long length) 394 { 395 X509_PUBKEY *xpk; 396 EVP_PKEY *pktmp; 397 xpk = d2i_X509_PUBKEY(NULL, pp, length); 398 if(!xpk) return NULL; 399 pktmp = X509_PUBKEY_get(xpk); 400 X509_PUBKEY_free(xpk); 401 if(!pktmp) return NULL; 402 if(a) 403 { 404 EVP_PKEY_free(*a); 405 *a = pktmp; 406 } 407 return pktmp; 408 } 409 410int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp) 411 { 412 X509_PUBKEY *xpk=NULL; 413 int ret; 414 if(!a) return 0; 415 if(!X509_PUBKEY_set(&xpk, a)) return 0; 416 ret = i2d_X509_PUBKEY(xpk, pp); 417 X509_PUBKEY_free(xpk); 418 return ret; 419 } 420 421/* The following are equivalents but which return RSA and DSA 422 * keys 423 */ 424#ifndef OPENSSL_NO_RSA 425RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, 426 long length) 427 { 428 EVP_PKEY *pkey; 429 RSA *key; 430 const unsigned char *q; 431 q = *pp; 432 pkey = d2i_PUBKEY(NULL, &q, length); 433 if (!pkey) return NULL; 434 key = EVP_PKEY_get1_RSA(pkey); 435 EVP_PKEY_free(pkey); 436 if (!key) return NULL; 437 *pp = q; 438 if (a) 439 { 440 RSA_free(*a); 441 *a = key; 442 } 443 return key; 444 } 445 446int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp) 447 { 448 EVP_PKEY *pktmp; 449 int ret; 450 if (!a) return 0; 451 pktmp = EVP_PKEY_new(); 452 if (!pktmp) 453 { 454 ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE); 455 return 0; 456 } 457 EVP_PKEY_set1_RSA(pktmp, a); 458 ret = i2d_PUBKEY(pktmp, pp); 459 EVP_PKEY_free(pktmp); 460 return ret; 461 } 462#endif 463 464#ifndef OPENSSL_NO_DSA 465DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, 466 long length) 467 { 468 EVP_PKEY *pkey; 469 DSA *key; 470 const unsigned char *q; 471 q = *pp; 472 pkey = d2i_PUBKEY(NULL, &q, length); 473 if (!pkey) return NULL; 474 key = EVP_PKEY_get1_DSA(pkey); 475 EVP_PKEY_free(pkey); 476 if (!key) return NULL; 477 *pp = q; 478 if (a) 479 { 480 DSA_free(*a); 481 *a = key; 482 } 483 return key; 484 } 485 486int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) 487 { 488 EVP_PKEY *pktmp; 489 int ret; 490 if(!a) return 0; 491 pktmp = EVP_PKEY_new(); 492 if(!pktmp) 493 { 494 ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE); 495 return 0; 496 } 497 EVP_PKEY_set1_DSA(pktmp, a); 498 ret = i2d_PUBKEY(pktmp, pp); 499 EVP_PKEY_free(pktmp); 500 return ret; 501 } 502#endif 503 504#ifndef OPENSSL_NO_EC 505EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length) 506 { 507 EVP_PKEY *pkey; 508 EC_KEY *key; 509 const unsigned char *q; 510 q = *pp; 511 pkey = d2i_PUBKEY(NULL, &q, length); 512 if (!pkey) return(NULL); 513 key = EVP_PKEY_get1_EC_KEY(pkey); 514 EVP_PKEY_free(pkey); 515 if (!key) return(NULL); 516 *pp = q; 517 if (a) 518 { 519 EC_KEY_free(*a); 520 *a = key; 521 } 522 return(key); 523 } 524 525int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp) 526 { 527 EVP_PKEY *pktmp; 528 int ret; 529 if (!a) return(0); 530 if ((pktmp = EVP_PKEY_new()) == NULL) 531 { 532 ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE); 533 return(0); 534 } 535 EVP_PKEY_set1_EC_KEY(pktmp, a); 536 ret = i2d_PUBKEY(pktmp, pp); 537 EVP_PKEY_free(pktmp); 538 return(ret); 539 } 540#endif 541