x_pubkey.c revision 79998
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/asn1_mac.h> 62#include <openssl/x509.h> 63 64int i2d_X509_PUBKEY(X509_PUBKEY *a, unsigned char **pp) 65 { 66 M_ASN1_I2D_vars(a); 67 68 M_ASN1_I2D_len(a->algor, i2d_X509_ALGOR); 69 M_ASN1_I2D_len(a->public_key, i2d_ASN1_BIT_STRING); 70 71 M_ASN1_I2D_seq_total(); 72 73 M_ASN1_I2D_put(a->algor, i2d_X509_ALGOR); 74 M_ASN1_I2D_put(a->public_key, i2d_ASN1_BIT_STRING); 75 76 M_ASN1_I2D_finish(); 77 } 78 79X509_PUBKEY *d2i_X509_PUBKEY(X509_PUBKEY **a, unsigned char **pp, 80 long length) 81 { 82 M_ASN1_D2I_vars(a,X509_PUBKEY *,X509_PUBKEY_new); 83 84 M_ASN1_D2I_Init(); 85 M_ASN1_D2I_start_sequence(); 86 M_ASN1_D2I_get(ret->algor,d2i_X509_ALGOR); 87 M_ASN1_D2I_get(ret->public_key,d2i_ASN1_BIT_STRING); 88 if (ret->pkey != NULL) 89 { 90 EVP_PKEY_free(ret->pkey); 91 ret->pkey=NULL; 92 } 93 M_ASN1_D2I_Finish(a,X509_PUBKEY_free,ASN1_F_D2I_X509_PUBKEY); 94 } 95 96X509_PUBKEY *X509_PUBKEY_new(void) 97 { 98 X509_PUBKEY *ret=NULL; 99 ASN1_CTX c; 100 101 M_ASN1_New_Malloc(ret,X509_PUBKEY); 102 M_ASN1_New(ret->algor,X509_ALGOR_new); 103 M_ASN1_New(ret->public_key,M_ASN1_BIT_STRING_new); 104 ret->pkey=NULL; 105 return(ret); 106 M_ASN1_New_Error(ASN1_F_X509_PUBKEY_NEW); 107 } 108 109void X509_PUBKEY_free(X509_PUBKEY *a) 110 { 111 if (a == NULL) return; 112 X509_ALGOR_free(a->algor); 113 M_ASN1_BIT_STRING_free(a->public_key); 114 if (a->pkey != NULL) EVP_PKEY_free(a->pkey); 115 OPENSSL_free(a); 116 } 117 118int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) 119 { 120 int ok=0; 121 X509_PUBKEY *pk; 122 X509_ALGOR *a; 123 ASN1_OBJECT *o; 124 unsigned char *s,*p; 125 int i; 126 127 if (x == NULL) return(0); 128 129 if ((pk=X509_PUBKEY_new()) == NULL) goto err; 130 a=pk->algor; 131 132 /* set the algorithm id */ 133 if ((o=OBJ_nid2obj(pkey->type)) == NULL) goto err; 134 ASN1_OBJECT_free(a->algorithm); 135 a->algorithm=o; 136 137 /* Set the parameter list */ 138 if (!pkey->save_parameters || (pkey->type == EVP_PKEY_RSA)) 139 { 140 if ((a->parameter == NULL) || 141 (a->parameter->type != V_ASN1_NULL)) 142 { 143 ASN1_TYPE_free(a->parameter); 144 a->parameter=ASN1_TYPE_new(); 145 a->parameter->type=V_ASN1_NULL; 146 } 147 } 148 else 149#ifndef NO_DSA 150 if (pkey->type == EVP_PKEY_DSA) 151 { 152 unsigned char *pp; 153 DSA *dsa; 154 155 dsa=pkey->pkey.dsa; 156 dsa->write_params=0; 157 ASN1_TYPE_free(a->parameter); 158 i=i2d_DSAparams(dsa,NULL); 159 p=(unsigned char *)OPENSSL_malloc(i); 160 pp=p; 161 i2d_DSAparams(dsa,&pp); 162 a->parameter=ASN1_TYPE_new(); 163 a->parameter->type=V_ASN1_SEQUENCE; 164 a->parameter->value.sequence=ASN1_STRING_new(); 165 ASN1_STRING_set(a->parameter->value.sequence,p,i); 166 OPENSSL_free(p); 167 } 168 else 169#endif 170 { 171 X509err(X509_F_X509_PUBKEY_SET,X509_R_UNSUPPORTED_ALGORITHM); 172 goto err; 173 } 174 175 if ((i=i2d_PublicKey(pkey,NULL)) <= 0) goto err; 176 if ((s=(unsigned char *)OPENSSL_malloc(i+1)) == NULL) goto err; 177 p=s; 178 i2d_PublicKey(pkey,&p); 179 if (!M_ASN1_BIT_STRING_set(pk->public_key,s,i)) goto err; 180 /* Set number of unused bits to zero */ 181 pk->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); 182 pk->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT; 183 184 OPENSSL_free(s); 185 186#if 0 187 CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY); 188 pk->pkey=pkey; 189#endif 190 191 if (*x != NULL) 192 X509_PUBKEY_free(*x); 193 194 *x=pk; 195 pk=NULL; 196 197 ok=1; 198err: 199 if (pk != NULL) X509_PUBKEY_free(pk); 200 return(ok); 201 } 202 203EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) 204 { 205 EVP_PKEY *ret=NULL; 206 long j; 207 int type; 208 unsigned char *p; 209#ifndef NO_DSA 210 X509_ALGOR *a; 211#endif 212 213 if (key == NULL) goto err; 214 215 if (key->pkey != NULL) 216 { 217 CRYPTO_add(&key->pkey->references,1,CRYPTO_LOCK_EVP_PKEY); 218 return(key->pkey); 219 } 220 221 if (key->public_key == NULL) goto err; 222 223 type=OBJ_obj2nid(key->algor->algorithm); 224 p=key->public_key->data; 225 j=key->public_key->length; 226 if ((ret=d2i_PublicKey(type,NULL,&p,(long)j)) == NULL) 227 { 228 X509err(X509_F_X509_PUBKEY_GET,X509_R_ERR_ASN1_LIB); 229 goto err; 230 } 231 ret->save_parameters=0; 232 233#ifndef NO_DSA 234 a=key->algor; 235 if (ret->type == EVP_PKEY_DSA) 236 { 237 if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE)) 238 { 239 ret->pkey.dsa->write_params=0; 240 p=a->parameter->value.sequence->data; 241 j=a->parameter->value.sequence->length; 242 if (!d2i_DSAparams(&ret->pkey.dsa,&p,(long)j)) 243 goto err; 244 } 245 ret->save_parameters=1; 246 } 247#endif 248 key->pkey=ret; 249 CRYPTO_add(&ret->references,1,CRYPTO_LOCK_EVP_PKEY); 250 return(ret); 251err: 252 if (ret != NULL) 253 EVP_PKEY_free(ret); 254 return(NULL); 255 } 256 257/* Now two pseudo ASN1 routines that take an EVP_PKEY structure 258 * and encode or decode as X509_PUBKEY 259 */ 260 261EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, unsigned char **pp, 262 long length) 263{ 264 X509_PUBKEY *xpk; 265 EVP_PKEY *pktmp; 266 xpk = d2i_X509_PUBKEY(NULL, pp, length); 267 if(!xpk) return NULL; 268 pktmp = X509_PUBKEY_get(xpk); 269 X509_PUBKEY_free(xpk); 270 if(!pktmp) return NULL; 271 if(a) { 272 EVP_PKEY_free(*a); 273 *a = pktmp; 274 } 275 return pktmp; 276} 277 278int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp) 279{ 280 X509_PUBKEY *xpk=NULL; 281 int ret; 282 if(!a) return 0; 283 if(!X509_PUBKEY_set(&xpk, a)) return 0; 284 ret = i2d_X509_PUBKEY(xpk, pp); 285 X509_PUBKEY_free(xpk); 286 return ret; 287} 288 289/* The following are equivalents but which return RSA and DSA 290 * keys 291 */ 292#ifndef NO_RSA 293RSA *d2i_RSA_PUBKEY(RSA **a, unsigned char **pp, 294 long length) 295{ 296 EVP_PKEY *pkey; 297 RSA *key; 298 unsigned char *q; 299 q = *pp; 300 pkey = d2i_PUBKEY(NULL, &q, length); 301 if(!pkey) return NULL; 302 key = EVP_PKEY_get1_RSA(pkey); 303 EVP_PKEY_free(pkey); 304 if(!key) return NULL; 305 *pp = q; 306 if(a) { 307 RSA_free(*a); 308 *a = key; 309 } 310 return key; 311} 312 313int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp) 314{ 315 EVP_PKEY *pktmp; 316 int ret; 317 if(!a) return 0; 318 pktmp = EVP_PKEY_new(); 319 if(!pktmp) { 320 ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE); 321 return 0; 322 } 323 EVP_PKEY_set1_RSA(pktmp, a); 324 ret = i2d_PUBKEY(pktmp, pp); 325 EVP_PKEY_free(pktmp); 326 return ret; 327} 328#endif 329 330#ifndef NO_DSA 331DSA *d2i_DSA_PUBKEY(DSA **a, unsigned char **pp, 332 long length) 333{ 334 EVP_PKEY *pkey; 335 DSA *key; 336 unsigned char *q; 337 q = *pp; 338 pkey = d2i_PUBKEY(NULL, &q, length); 339 if(!pkey) return NULL; 340 key = EVP_PKEY_get1_DSA(pkey); 341 EVP_PKEY_free(pkey); 342 if(!key) return NULL; 343 *pp = q; 344 if(a) { 345 DSA_free(*a); 346 *a = key; 347 } 348 return key; 349} 350 351int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) 352{ 353 EVP_PKEY *pktmp; 354 int ret; 355 if(!a) return 0; 356 pktmp = EVP_PKEY_new(); 357 if(!pktmp) { 358 ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE); 359 return 0; 360 } 361 EVP_PKEY_set1_DSA(pktmp, a); 362 ret = i2d_PUBKEY(pktmp, pp); 363 EVP_PKEY_free(pktmp); 364 return ret; 365} 366#endif 367