/src/openssl111/crypto/x509/x_pubkey.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. | 
| 3 |  |  * | 
| 4 |  |  * Licensed under the OpenSSL license (the "License").  You may not use | 
| 5 |  |  * this file except in compliance with the License.  You can obtain a copy | 
| 6 |  |  * in the file LICENSE in the source distribution or at | 
| 7 |  |  * https://www.openssl.org/source/license.html | 
| 8 |  |  */ | 
| 9 |  |  | 
| 10 |  | #include <stdio.h> | 
| 11 |  | #include "internal/cryptlib.h" | 
| 12 |  | #include <openssl/asn1t.h> | 
| 13 |  | #include <openssl/x509.h> | 
| 14 |  | #include "crypto/asn1.h" | 
| 15 |  | #include "crypto/evp.h" | 
| 16 |  | #include "crypto/x509.h" | 
| 17 |  | #include <openssl/rsa.h> | 
| 18 |  | #include <openssl/dsa.h> | 
| 19 |  |  | 
| 20 |  | struct X509_pubkey_st { | 
| 21 |  |     X509_ALGOR *algor; | 
| 22 |  |     ASN1_BIT_STRING *public_key; | 
| 23 |  |     EVP_PKEY *pkey; | 
| 24 |  | }; | 
| 25 |  |  | 
| 26 |  | static int x509_pubkey_decode(EVP_PKEY **pk, X509_PUBKEY *key); | 
| 27 |  |  | 
| 28 |  | /* Minor tweak to operation: free up EVP_PKEY */ | 
| 29 |  | static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, | 
| 30 |  |                      void *exarg) | 
| 31 | 211k | { | 
| 32 | 211k |     if (operation == ASN1_OP_FREE_POST) { | 
| 33 | 35.3k |         X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; | 
| 34 | 35.3k |         EVP_PKEY_free(pubkey->pkey); | 
| 35 | 176k |     } else if (operation == ASN1_OP_D2I_POST) { | 
| 36 |  |         /* Attempt to decode public key and cache in pubkey structure. */ | 
| 37 | 35.1k |         X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; | 
| 38 | 35.1k |         EVP_PKEY_free(pubkey->pkey); | 
| 39 | 35.1k |         pubkey->pkey = NULL; | 
| 40 |  |         /* | 
| 41 |  |          * Opportunistically decode the key but remove any non fatal errors | 
| 42 |  |          * from the queue. Subsequent explicit attempts to decode/use the key | 
| 43 |  |          * will return an appropriate error. | 
| 44 |  |          */ | 
| 45 | 35.1k |         ERR_set_mark(); | 
| 46 | 35.1k |         if (x509_pubkey_decode(&pubkey->pkey, pubkey) == -1) | 
| 47 | 0 |             return 0; | 
| 48 | 35.1k |         ERR_pop_to_mark(); | 
| 49 | 35.1k |     } | 
| 50 | 211k |     return 1; | 
| 51 | 211k | } | 
| 52 |  |  | 
| 53 |  | ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = { | 
| 54 |  |         ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), | 
| 55 |  |         ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING) | 
| 56 |  | } ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY) | 
| 57 |  |  | 
| 58 |  | IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY) | 
| 59 |  |  | 
| 60 |  | int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) | 
| 61 | 0 | { | 
| 62 | 0 |     X509_PUBKEY *pk = NULL; | 
| 63 |  | 
 | 
| 64 | 0 |     if (x == NULL) | 
| 65 | 0 |         return 0; | 
| 66 |  |  | 
| 67 | 0 |     if ((pk = X509_PUBKEY_new()) == NULL) | 
| 68 | 0 |         goto error; | 
| 69 |  |  | 
| 70 | 0 |     if (pkey->ameth) { | 
| 71 | 0 |         if (pkey->ameth->pub_encode) { | 
| 72 | 0 |             if (!pkey->ameth->pub_encode(pk, pkey)) { | 
| 73 | 0 |                 X509err(X509_F_X509_PUBKEY_SET, | 
| 74 | 0 |                         X509_R_PUBLIC_KEY_ENCODE_ERROR); | 
| 75 | 0 |                 goto error; | 
| 76 | 0 |             } | 
| 77 | 0 |         } else { | 
| 78 | 0 |             X509err(X509_F_X509_PUBKEY_SET, X509_R_METHOD_NOT_SUPPORTED); | 
| 79 | 0 |             goto error; | 
| 80 | 0 |         } | 
| 81 | 0 |     } else { | 
| 82 | 0 |         X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM); | 
| 83 | 0 |         goto error; | 
| 84 | 0 |     } | 
| 85 |  |  | 
| 86 | 0 |     X509_PUBKEY_free(*x); | 
| 87 | 0 |     *x = pk; | 
| 88 | 0 |     pk->pkey = pkey; | 
| 89 | 0 |     EVP_PKEY_up_ref(pkey); | 
| 90 | 0 |     return 1; | 
| 91 |  |  | 
| 92 | 0 |  error: | 
| 93 | 0 |     X509_PUBKEY_free(pk); | 
| 94 | 0 |     return 0; | 
| 95 | 0 | } | 
| 96 |  |  | 
| 97 |  | /* | 
| 98 |  |  * Attempt to decode a public key. | 
| 99 |  |  * Returns 1 on success, 0 for a decode failure and -1 for a fatal | 
| 100 |  |  * error e.g. malloc failure. | 
| 101 |  |  */ | 
| 102 |  |  | 
| 103 |  |  | 
| 104 |  | static int x509_pubkey_decode(EVP_PKEY **ppkey, X509_PUBKEY *key) | 
| 105 | 35.1k | { | 
| 106 | 35.1k |     EVP_PKEY *pkey = EVP_PKEY_new(); | 
| 107 |  |  | 
| 108 | 35.1k |     if (pkey == NULL) { | 
| 109 | 0 |         X509err(X509_F_X509_PUBKEY_DECODE, ERR_R_MALLOC_FAILURE); | 
| 110 | 0 |         return -1; | 
| 111 | 0 |     } | 
| 112 |  |  | 
| 113 | 35.1k |     if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(key->algor->algorithm))) { | 
| 114 | 1.31k |         X509err(X509_F_X509_PUBKEY_DECODE, X509_R_UNSUPPORTED_ALGORITHM); | 
| 115 | 1.31k |         goto error; | 
| 116 | 1.31k |     } | 
| 117 |  |  | 
| 118 | 33.8k |     if (pkey->ameth->pub_decode) { | 
| 119 |  |         /* | 
| 120 |  |          * Treat any failure of pub_decode as a decode error. In | 
| 121 |  |          * future we could have different return codes for decode | 
| 122 |  |          * errors and fatal errors such as malloc failure. | 
| 123 |  |          */ | 
| 124 | 33.8k |         if (!pkey->ameth->pub_decode(pkey, key)) { | 
| 125 | 18.8k |             X509err(X509_F_X509_PUBKEY_DECODE, X509_R_PUBLIC_KEY_DECODE_ERROR); | 
| 126 | 18.8k |             goto error; | 
| 127 | 18.8k |         } | 
| 128 | 33.8k |     } else { | 
| 129 | 0 |         X509err(X509_F_X509_PUBKEY_DECODE, X509_R_METHOD_NOT_SUPPORTED); | 
| 130 | 0 |         goto error; | 
| 131 | 0 |     } | 
| 132 |  |  | 
| 133 | 15.0k |     *ppkey = pkey; | 
| 134 | 15.0k |     return 1; | 
| 135 |  |  | 
| 136 | 20.1k |  error: | 
| 137 | 20.1k |     EVP_PKEY_free(pkey); | 
| 138 | 20.1k |     return 0; | 
| 139 | 33.8k | } | 
| 140 |  |  | 
| 141 |  | EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key) | 
| 142 | 0 | { | 
| 143 | 0 |     EVP_PKEY *ret = NULL; | 
| 144 |  | 
 | 
| 145 | 0 |     if (key == NULL || key->public_key == NULL) | 
| 146 | 0 |         return NULL; | 
| 147 |  |  | 
| 148 | 0 |     if (key->pkey != NULL) | 
| 149 | 0 |         return key->pkey; | 
| 150 |  |  | 
| 151 |  |     /* | 
| 152 |  |      * When the key ASN.1 is initially parsed an attempt is made to | 
| 153 |  |      * decode the public key and cache the EVP_PKEY structure. If this | 
| 154 |  |      * operation fails the cached value will be NULL. Parsing continues | 
| 155 |  |      * to allow parsing of unknown key types or unsupported forms. | 
| 156 |  |      * We repeat the decode operation so the appropriate errors are left | 
| 157 |  |      * in the queue. | 
| 158 |  |      */ | 
| 159 | 0 |     x509_pubkey_decode(&ret, key); | 
| 160 |  |     /* If decode doesn't fail something bad happened */ | 
| 161 | 0 |     if (ret != NULL) { | 
| 162 | 0 |         X509err(X509_F_X509_PUBKEY_GET0, ERR_R_INTERNAL_ERROR); | 
| 163 | 0 |         EVP_PKEY_free(ret); | 
| 164 | 0 |     } | 
| 165 |  | 
 | 
| 166 | 0 |     return NULL; | 
| 167 | 0 | } | 
| 168 |  |  | 
| 169 |  | EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) | 
| 170 | 0 | { | 
| 171 | 0 |     EVP_PKEY *ret = X509_PUBKEY_get0(key); | 
| 172 |  | 
 | 
| 173 | 0 |     if (ret != NULL && !EVP_PKEY_up_ref(ret)) { | 
| 174 | 0 |         X509err(X509_F_X509_PUBKEY_GET, ERR_R_INTERNAL_ERROR); | 
| 175 | 0 |         ret = NULL; | 
| 176 | 0 |     } | 
| 177 | 0 |     return ret; | 
| 178 | 0 | } | 
| 179 |  |  | 
| 180 |  | /* | 
| 181 |  |  * Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or | 
| 182 |  |  * decode as X509_PUBKEY | 
| 183 |  |  */ | 
| 184 |  |  | 
| 185 |  | EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length) | 
| 186 | 0 | { | 
| 187 | 0 |     X509_PUBKEY *xpk; | 
| 188 | 0 |     EVP_PKEY *pktmp; | 
| 189 | 0 |     const unsigned char *q; | 
| 190 | 0 |     q = *pp; | 
| 191 | 0 |     xpk = d2i_X509_PUBKEY(NULL, &q, length); | 
| 192 | 0 |     if (!xpk) | 
| 193 | 0 |         return NULL; | 
| 194 | 0 |     pktmp = X509_PUBKEY_get(xpk); | 
| 195 | 0 |     X509_PUBKEY_free(xpk); | 
| 196 | 0 |     if (!pktmp) | 
| 197 | 0 |         return NULL; | 
| 198 | 0 |     *pp = q; | 
| 199 | 0 |     if (a) { | 
| 200 | 0 |         EVP_PKEY_free(*a); | 
| 201 | 0 |         *a = pktmp; | 
| 202 | 0 |     } | 
| 203 | 0 |     return pktmp; | 
| 204 | 0 | } | 
| 205 |  |  | 
| 206 |  | int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp) | 
| 207 | 0 | { | 
| 208 | 0 |     X509_PUBKEY *xpk = NULL; | 
| 209 | 0 |     int ret; | 
| 210 | 0 |     if (!a) | 
| 211 | 0 |         return 0; | 
| 212 | 0 |     if (!X509_PUBKEY_set(&xpk, a)) | 
| 213 | 0 |         return -1; | 
| 214 | 0 |     ret = i2d_X509_PUBKEY(xpk, pp); | 
| 215 | 0 |     X509_PUBKEY_free(xpk); | 
| 216 | 0 |     return ret; | 
| 217 | 0 | } | 
| 218 |  |  | 
| 219 |  | /* | 
| 220 |  |  * The following are equivalents but which return RSA and DSA keys | 
| 221 |  |  */ | 
| 222 |  | #ifndef OPENSSL_NO_RSA | 
| 223 |  | RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length) | 
| 224 | 0 | { | 
| 225 | 0 |     EVP_PKEY *pkey; | 
| 226 | 0 |     RSA *key; | 
| 227 | 0 |     const unsigned char *q; | 
| 228 | 0 |     q = *pp; | 
| 229 | 0 |     pkey = d2i_PUBKEY(NULL, &q, length); | 
| 230 | 0 |     if (!pkey) | 
| 231 | 0 |         return NULL; | 
| 232 | 0 |     key = EVP_PKEY_get1_RSA(pkey); | 
| 233 | 0 |     EVP_PKEY_free(pkey); | 
| 234 | 0 |     if (!key) | 
| 235 | 0 |         return NULL; | 
| 236 | 0 |     *pp = q; | 
| 237 | 0 |     if (a) { | 
| 238 | 0 |         RSA_free(*a); | 
| 239 | 0 |         *a = key; | 
| 240 | 0 |     } | 
| 241 | 0 |     return key; | 
| 242 | 0 | } | 
| 243 |  |  | 
| 244 |  | int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp) | 
| 245 | 0 | { | 
| 246 | 0 |     EVP_PKEY *pktmp; | 
| 247 | 0 |     int ret; | 
| 248 | 0 |     if (!a) | 
| 249 | 0 |         return 0; | 
| 250 | 0 |     pktmp = EVP_PKEY_new(); | 
| 251 | 0 |     if (pktmp == NULL) { | 
| 252 | 0 |         ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE); | 
| 253 | 0 |         return -1; | 
| 254 | 0 |     } | 
| 255 | 0 |     EVP_PKEY_set1_RSA(pktmp, a); | 
| 256 | 0 |     ret = i2d_PUBKEY(pktmp, pp); | 
| 257 | 0 |     EVP_PKEY_free(pktmp); | 
| 258 | 0 |     return ret; | 
| 259 | 0 | } | 
| 260 |  | #endif | 
| 261 |  |  | 
| 262 |  | #ifndef OPENSSL_NO_DSA | 
| 263 |  | DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length) | 
| 264 | 0 | { | 
| 265 | 0 |     EVP_PKEY *pkey; | 
| 266 | 0 |     DSA *key; | 
| 267 | 0 |     const unsigned char *q; | 
| 268 | 0 |     q = *pp; | 
| 269 | 0 |     pkey = d2i_PUBKEY(NULL, &q, length); | 
| 270 | 0 |     if (!pkey) | 
| 271 | 0 |         return NULL; | 
| 272 | 0 |     key = EVP_PKEY_get1_DSA(pkey); | 
| 273 | 0 |     EVP_PKEY_free(pkey); | 
| 274 | 0 |     if (!key) | 
| 275 | 0 |         return NULL; | 
| 276 | 0 |     *pp = q; | 
| 277 | 0 |     if (a) { | 
| 278 | 0 |         DSA_free(*a); | 
| 279 | 0 |         *a = key; | 
| 280 | 0 |     } | 
| 281 | 0 |     return key; | 
| 282 | 0 | } | 
| 283 |  |  | 
| 284 |  | int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) | 
| 285 | 0 | { | 
| 286 | 0 |     EVP_PKEY *pktmp; | 
| 287 | 0 |     int ret; | 
| 288 | 0 |     if (!a) | 
| 289 | 0 |         return 0; | 
| 290 | 0 |     pktmp = EVP_PKEY_new(); | 
| 291 | 0 |     if (pktmp == NULL) { | 
| 292 | 0 |         ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE); | 
| 293 | 0 |         return -1; | 
| 294 | 0 |     } | 
| 295 | 0 |     EVP_PKEY_set1_DSA(pktmp, a); | 
| 296 | 0 |     ret = i2d_PUBKEY(pktmp, pp); | 
| 297 | 0 |     EVP_PKEY_free(pktmp); | 
| 298 | 0 |     return ret; | 
| 299 | 0 | } | 
| 300 |  | #endif | 
| 301 |  |  | 
| 302 |  | #ifndef OPENSSL_NO_EC | 
| 303 |  | EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length) | 
| 304 | 0 | { | 
| 305 | 0 |     EVP_PKEY *pkey; | 
| 306 | 0 |     EC_KEY *key; | 
| 307 | 0 |     const unsigned char *q; | 
| 308 | 0 |     q = *pp; | 
| 309 | 0 |     pkey = d2i_PUBKEY(NULL, &q, length); | 
| 310 | 0 |     if (!pkey) | 
| 311 | 0 |         return NULL; | 
| 312 | 0 |     key = EVP_PKEY_get1_EC_KEY(pkey); | 
| 313 | 0 |     EVP_PKEY_free(pkey); | 
| 314 | 0 |     if (!key) | 
| 315 | 0 |         return NULL; | 
| 316 | 0 |     *pp = q; | 
| 317 | 0 |     if (a) { | 
| 318 | 0 |         EC_KEY_free(*a); | 
| 319 | 0 |         *a = key; | 
| 320 | 0 |     } | 
| 321 | 0 |     return key; | 
| 322 | 0 | } | 
| 323 |  |  | 
| 324 |  | int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp) | 
| 325 | 0 | { | 
| 326 | 0 |     EVP_PKEY *pktmp; | 
| 327 | 0 |     int ret; | 
| 328 | 0 |     if (!a) | 
| 329 | 0 |         return 0; | 
| 330 | 0 |     if ((pktmp = EVP_PKEY_new()) == NULL) { | 
| 331 | 0 |         ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE); | 
| 332 | 0 |         return -1; | 
| 333 | 0 |     } | 
| 334 | 0 |     EVP_PKEY_set1_EC_KEY(pktmp, a); | 
| 335 | 0 |     ret = i2d_PUBKEY(pktmp, pp); | 
| 336 | 0 |     EVP_PKEY_free(pktmp); | 
| 337 | 0 |     return ret; | 
| 338 | 0 | } | 
| 339 |  | #endif | 
| 340 |  |  | 
| 341 |  | int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, | 
| 342 |  |                            int ptype, void *pval, | 
| 343 |  |                            unsigned char *penc, int penclen) | 
| 344 | 0 | { | 
| 345 | 0 |     if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval)) | 
| 346 | 0 |         return 0; | 
| 347 | 0 |     if (penc) { | 
| 348 | 0 |         OPENSSL_free(pub->public_key->data); | 
| 349 | 0 |         pub->public_key->data = penc; | 
| 350 | 0 |         pub->public_key->length = penclen; | 
| 351 |  |         /* Set number of unused bits to zero */ | 
| 352 | 0 |         pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); | 
| 353 | 0 |         pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; | 
| 354 | 0 |     } | 
| 355 | 0 |     return 1; | 
| 356 | 0 | } | 
| 357 |  |  | 
| 358 |  | int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, | 
| 359 |  |                            const unsigned char **pk, int *ppklen, | 
| 360 |  |                            X509_ALGOR **pa, X509_PUBKEY *pub) | 
| 361 | 33.8k | { | 
| 362 | 33.8k |     if (ppkalg) | 
| 363 | 0 |         *ppkalg = pub->algor->algorithm; | 
| 364 | 33.8k |     if (pk) { | 
| 365 | 33.8k |         *pk = pub->public_key->data; | 
| 366 | 33.8k |         *ppklen = pub->public_key->length; | 
| 367 | 33.8k |     } | 
| 368 | 33.8k |     if (pa) | 
| 369 | 33.8k |         *pa = pub->algor; | 
| 370 | 33.8k |     return 1; | 
| 371 | 33.8k | } | 
| 372 |  |  | 
| 373 |  | ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) | 
| 374 | 0 | { | 
| 375 | 0 |     if (x == NULL) | 
| 376 | 0 |         return NULL; | 
| 377 | 0 |     return x->cert_info.key->public_key; | 
| 378 | 0 | } |