1 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
   2  * project 2006.
   3  */
   4 /* ====================================================================
   5  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
   6  *
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  *
  11  * 1. Redistributions of source code must retain the above copyright
  12  *    notice, this list of conditions and the following disclaimer.
  13  *
  14  * 2. Redistributions in binary form must reproduce the above copyright
  15  *    notice, this list of conditions and the following disclaimer in
  16  *    the documentation and/or other materials provided with the
  17  *    distribution.
  18  *
  19  * 3. All advertising materials mentioning features or use of this
  20  *    software must display the following acknowledgment:
  21  *    "This product includes software developed by the OpenSSL Project
  22  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  23  *
  24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  25  *    endorse or promote products derived from this software without
  26  *    prior written permission. For written permission, please contact
  27  *    licensing@OpenSSL.org.
  28  *
  29  * 5. Products derived from this software may not be called "OpenSSL"
  30  *    nor may "OpenSSL" appear in their names without prior written
  31  *    permission of the OpenSSL Project.
  32  *
  33  * 6. Redistributions of any form whatsoever must retain the following
  34  *    acknowledgment:
  35  *    "This product includes software developed by the OpenSSL Project
  36  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  37  *
  38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  49  * OF THE POSSIBILITY OF SUCH DAMAGE.
  50  * ====================================================================
  51  *
  52  * This product includes cryptographic software written by Eric Young
  53  * (eay@cryptsoft.com).  This product includes software written by Tim
  54  * Hudson (tjh@cryptsoft.com).
  55  *
  56  */
  57 
  58 #include <stdio.h>
  59 #include "cryptlib.h"
  60 #include <openssl/asn1t.h>
  61 #include <openssl/x509.h>
  62 #ifndef OPENSSL_NO_ENGINE
  63 #include <openssl/engine.h>
  64 #endif
  65 #include "asn1_locl.h"
  66 
  67 extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
  68 extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
  69 extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
  70 extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
  71 extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
  72 extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
  73 
  74 /* Keep this sorted in type order !! */
  75 static const EVP_PKEY_ASN1_METHOD *standard_methods[] =
  76         {
  77 #ifndef OPENSSL_NO_RSA
  78         &rsa_asn1_meths[0],
  79         &rsa_asn1_meths[1],
  80 #endif
  81 #ifndef OPENSSL_NO_DH
  82         &dh_asn1_meth,
  83 #endif
  84 #ifndef OPENSSL_NO_DSA
  85         &dsa_asn1_meths[0],
  86         &dsa_asn1_meths[1],
  87         &dsa_asn1_meths[2],
  88         &dsa_asn1_meths[3],
  89         &dsa_asn1_meths[4],
  90 #endif
  91 #ifndef OPENSSL_NO_EC
  92         &eckey_asn1_meth,
  93 #endif
  94         &hmac_asn1_meth,
  95         &cmac_asn1_meth
  96         };
  97 
  98 typedef int sk_cmp_fn_type(const char * const *a, const char * const *b);
  99 DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD)
 100 static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
 101 
 102 
 103 
 104 #ifdef TEST
 105 void main()
 106         {
 107         int i;
 108         for (i = 0;
 109                 i < sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
 110                 i++)
 111                 fprintf(stderr, "Number %d id=%d (%s)\n", i,
 112                         standard_methods[i]->pkey_id,
 113                         OBJ_nid2sn(standard_methods[i]->pkey_id));
 114         }
 115 #endif
 116 
 117 DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
 118                            const EVP_PKEY_ASN1_METHOD *, ameth);
 119 
 120 static int ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a,
 121                      const EVP_PKEY_ASN1_METHOD * const *b)
 122         {
 123         return ((*a)->pkey_id - (*b)->pkey_id);
 124         }
 125 
 126 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
 127                              const EVP_PKEY_ASN1_METHOD *, ameth);
 128 
 129 int EVP_PKEY_asn1_get_count(void)
 130         {
 131         int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
 132         if (app_methods)
 133                 num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
 134         return num;
 135         }
 136 
 137 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
 138         {
 139         int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
 140         if (idx < 0)
 141                 return NULL;
 142         if (idx < num)
 143                 return standard_methods[idx];
 144         idx -= num;
 145         return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
 146         }
 147 
 148 static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
 149         {
 150         EVP_PKEY_ASN1_METHOD tmp;
 151         const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
 152         tmp.pkey_id = type;
 153         if (app_methods)
 154                 {
 155                 int idx;
 156                 idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp);
 157                 if (idx >= 0)
 158                         return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
 159                 }
 160         ret = OBJ_bsearch_ameth(&t, standard_methods,
 161                           sizeof(standard_methods)
 162                           /sizeof(EVP_PKEY_ASN1_METHOD *));
 163         if (!ret || !*ret)
 164                 return NULL;
 165         return *ret;
 166         }
 167 
 168 /* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL
 169  * also search through engines and set *pe to a functional reference
 170  * to the engine implementing 'type' or NULL if no engine implements
 171  * it.
 172  */
 173 
 174 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
 175         {
 176         const EVP_PKEY_ASN1_METHOD *t;
 177 
 178         for (;;)
 179                 {
 180                 t = pkey_asn1_find(type);
 181                 if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
 182                         break;
 183                 type = t->pkey_base_id;
 184                 }
 185         if (pe)
 186                 {
 187 #ifndef OPENSSL_NO_ENGINE
 188                 ENGINE *e;
 189                 /* type will contain the final unaliased type */
 190                 e = ENGINE_get_pkey_asn1_meth_engine(type);
 191                 if (e)
 192                         {
 193                         *pe = e;
 194                         return ENGINE_get_pkey_asn1_meth(e, type);
 195                         }
 196 #endif
 197                 *pe = NULL;
 198                 }
 199         return t;
 200         }
 201 
 202 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
 203                                         const char *str, int len)
 204         {
 205         int i;
 206         const EVP_PKEY_ASN1_METHOD *ameth;
 207         if (len == -1)
 208                 len = strlen(str);
 209         if (pe)
 210                 {
 211 #ifndef OPENSSL_NO_ENGINE
 212                 ENGINE *e;
 213                 ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
 214                 if (ameth)
 215                         {
 216                         /* Convert structural into
 217                          * functional reference
 218                          */
 219                         if (!ENGINE_init(e))
 220                                 ameth = NULL;
 221                         ENGINE_free(e);
 222                         *pe = e;
 223                         return ameth;
 224                         }
 225 #endif
 226                 *pe = NULL;
 227                 }
 228         for (i = 0; i < EVP_PKEY_asn1_get_count(); i++)
 229                 {
 230                 ameth = EVP_PKEY_asn1_get0(i);
 231                 if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
 232                         continue;
 233                 if (((int)strlen(ameth->pem_str) == len) &&
 234                         !strncasecmp(ameth->pem_str, str, len))
 235                         return ameth;
 236                 }
 237         return NULL;
 238         }
 239 
 240 int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
 241         {
 242         if (app_methods == NULL)
 243                 {
 244                 app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
 245                 if (!app_methods)
 246                         return 0;
 247                 }
 248         if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
 249                 return 0;
 250         sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
 251         return 1;
 252         }
 253 
 254 int EVP_PKEY_asn1_add_alias(int to, int from)
 255         {
 256         EVP_PKEY_ASN1_METHOD *ameth;
 257         ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
 258         if (!ameth)
 259                 return 0;
 260         ameth->pkey_base_id = to;
 261         if (!EVP_PKEY_asn1_add0(ameth))
 262                 {
 263                 EVP_PKEY_asn1_free(ameth);
 264                 return 0;
 265                 }
 266         return 1;
 267         }
 268 
 269 int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, int *ppkey_flags,
 270                                 const char **pinfo, const char **ppem_str,
 271                                         const EVP_PKEY_ASN1_METHOD *ameth)
 272         {
 273         if (!ameth)
 274                 return 0;
 275         if (ppkey_id)
 276                 *ppkey_id = ameth->pkey_id;
 277         if (ppkey_base_id)
 278                 *ppkey_base_id = ameth->pkey_base_id;
 279         if (ppkey_flags)
 280                 *ppkey_flags = ameth->pkey_flags;
 281         if (pinfo)
 282                 *pinfo = ameth->info;
 283         if (ppem_str)
 284                 *ppem_str = ameth->pem_str;
 285         return 1;
 286         }
 287 
 288 const EVP_PKEY_ASN1_METHOD* EVP_PKEY_get0_asn1(EVP_PKEY *pkey)
 289         {
 290         return pkey->ameth;
 291         }
 292 
 293 EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id, int flags,
 294                                         const char *pem_str, const char *info)
 295         {
 296         EVP_PKEY_ASN1_METHOD *ameth;
 297         ameth = OPENSSL_malloc(sizeof(EVP_PKEY_ASN1_METHOD));
 298         if (!ameth)
 299                 return NULL;
 300 
 301         memset(ameth, 0, sizeof(EVP_PKEY_ASN1_METHOD));
 302 
 303         ameth->pkey_id = id;
 304         ameth->pkey_base_id = id;
 305         ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
 306 
 307         if (info)
 308                 {
 309                 ameth->info = BUF_strdup(info);
 310                 if (!ameth->info)
 311                         goto err;
 312                 }
 313         else
 314                 ameth->info = NULL;
 315 
 316         if (pem_str)
 317                 {
 318                 ameth->pem_str = BUF_strdup(pem_str);
 319                 if (!ameth->pem_str)
 320                         goto err;
 321                 }
 322         else
 323                 ameth->pem_str = NULL;
 324 
 325         ameth->pub_decode = 0;
 326         ameth->pub_encode = 0;
 327         ameth->pub_cmp = 0;
 328         ameth->pub_print = 0;
 329 
 330         ameth->priv_decode = 0;
 331         ameth->priv_encode = 0;
 332         ameth->priv_print = 0;
 333 
 334         ameth->old_priv_encode = 0;
 335         ameth->old_priv_decode = 0;
 336 
 337         ameth->item_verify = 0;
 338         ameth->item_sign = 0;
 339 
 340         ameth->pkey_size = 0;
 341         ameth->pkey_bits = 0;
 342 
 343         ameth->param_decode = 0;
 344         ameth->param_encode = 0;
 345         ameth->param_missing = 0;
 346         ameth->param_copy = 0;
 347         ameth->param_cmp = 0;
 348         ameth->param_print = 0;
 349 
 350         ameth->pkey_free = 0;
 351         ameth->pkey_ctrl = 0;
 352 
 353         return ameth;
 354 
 355         err:
 356 
 357         EVP_PKEY_asn1_free(ameth);
 358         return NULL;
 359 
 360         }
 361 
 362 void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
 363                         const EVP_PKEY_ASN1_METHOD *src)
 364         {
 365 
 366         dst->pub_decode = src->pub_decode;
 367         dst->pub_encode = src->pub_encode;
 368         dst->pub_cmp = src->pub_cmp;
 369         dst->pub_print = src->pub_print;
 370 
 371         dst->priv_decode = src->priv_decode;
 372         dst->priv_encode = src->priv_encode;
 373         dst->priv_print = src->priv_print;
 374 
 375         dst->old_priv_encode = src->old_priv_encode;
 376         dst->old_priv_decode = src->old_priv_decode;
 377 
 378         dst->pkey_size = src->pkey_size;
 379         dst->pkey_bits = src->pkey_bits;
 380 
 381         dst->param_decode = src->param_decode;
 382         dst->param_encode = src->param_encode;
 383         dst->param_missing = src->param_missing;
 384         dst->param_copy = src->param_copy;
 385         dst->param_cmp = src->param_cmp;
 386         dst->param_print = src->param_print;
 387 
 388         dst->pkey_free = src->pkey_free;
 389         dst->pkey_ctrl = src->pkey_ctrl;
 390 
 391         dst->item_sign = src->item_sign;
 392         dst->item_verify = src->item_verify;
 393 
 394         }
 395 
 396 void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
 397         {
 398         if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC))
 399                 {
 400                 if (ameth->pem_str)
 401                         OPENSSL_free(ameth->pem_str);
 402                 if (ameth->info)
 403                         OPENSSL_free(ameth->info);
 404                 OPENSSL_free(ameth);
 405                 }
 406         }
 407 
 408 void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
 409                 int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub),
 410                 int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk),
 411                 int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
 412                 int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent,
 413                                                         ASN1_PCTX *pctx),
 414                 int (*pkey_size)(const EVP_PKEY *pk),
 415                 int (*pkey_bits)(const EVP_PKEY *pk))
 416         {
 417         ameth->pub_decode = pub_decode;
 418         ameth->pub_encode = pub_encode;
 419         ameth->pub_cmp = pub_cmp;
 420         ameth->pub_print = pub_print;
 421         ameth->pkey_size = pkey_size;
 422         ameth->pkey_bits = pkey_bits;
 423         }
 424 
 425 void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
 426                 int (*priv_decode)(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf),
 427                 int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk),
 428                 int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
 429                                                         ASN1_PCTX *pctx))
 430         {
 431         ameth->priv_decode = priv_decode;
 432         ameth->priv_encode = priv_encode;
 433         ameth->priv_print = priv_print;
 434         }
 435 
 436 void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
 437                 int (*param_decode)(EVP_PKEY *pkey,
 438                                 const unsigned char **pder, int derlen),
 439                 int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder),
 440                 int (*param_missing)(const EVP_PKEY *pk),
 441                 int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from),
 442                 int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
 443                 int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
 444                                                         ASN1_PCTX *pctx))
 445         {
 446         ameth->param_decode = param_decode;
 447         ameth->param_encode = param_encode;
 448         ameth->param_missing = param_missing;
 449         ameth->param_copy = param_copy;
 450         ameth->param_cmp = param_cmp;
 451         ameth->param_print = param_print;
 452         }
 453 
 454 void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
 455                 void (*pkey_free)(EVP_PKEY *pkey))
 456         {
 457         ameth->pkey_free = pkey_free;
 458         }
 459 
 460 void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
 461                 int (*pkey_ctrl)(EVP_PKEY *pkey, int op,
 462                                                         long arg1, void *arg2))
 463         {
 464         ameth->pkey_ctrl = pkey_ctrl;
 465         }