160662d10Schristos /*
2*1dcdf01fSchristos  * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
360662d10Schristos  *
4*1dcdf01fSchristos  * Licensed under the OpenSSL license (the "License").  You may not use
5*1dcdf01fSchristos  * this file except in compliance with the License.  You can obtain a copy
6*1dcdf01fSchristos  * in the file LICENSE in the source distribution or at
7*1dcdf01fSchristos  * https://www.openssl.org/source/license.html
860662d10Schristos  */
960662d10Schristos 
1060662d10Schristos #include <stddef.h>
1160662d10Schristos #include <string.h>
12*1dcdf01fSchristos #include "internal/cryptlib.h"
13*1dcdf01fSchristos #include "internal/refcount.h"
1460662d10Schristos #include <openssl/asn1.h>
1560662d10Schristos #include <openssl/asn1t.h>
1660662d10Schristos #include <openssl/objects.h>
1760662d10Schristos #include <openssl/err.h>
18*1dcdf01fSchristos #include "asn1_local.h"
1960662d10Schristos 
2060662d10Schristos /* Utility functions for manipulating fields and offsets */
2160662d10Schristos 
2260662d10Schristos /* Add 'offset' to 'addr' */
2360662d10Schristos #define offset2ptr(addr, offset) (void *)(((char *) addr) + offset)
2460662d10Schristos 
2560662d10Schristos /*
2660662d10Schristos  * Given an ASN1_ITEM CHOICE type return the selector value
2760662d10Schristos  */
2860662d10Schristos 
asn1_get_choice_selector(ASN1_VALUE ** pval,const ASN1_ITEM * it)2960662d10Schristos int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it)
3060662d10Schristos {
3160662d10Schristos     int *sel = offset2ptr(*pval, it->utype);
3260662d10Schristos     return *sel;
3360662d10Schristos }
3460662d10Schristos 
3560662d10Schristos /*
3660662d10Schristos  * Given an ASN1_ITEM CHOICE type set the selector value, return old value.
3760662d10Schristos  */
3860662d10Schristos 
asn1_set_choice_selector(ASN1_VALUE ** pval,int value,const ASN1_ITEM * it)3960662d10Schristos int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
4060662d10Schristos                              const ASN1_ITEM *it)
4160662d10Schristos {
4260662d10Schristos     int *sel, ret;
4360662d10Schristos     sel = offset2ptr(*pval, it->utype);
4460662d10Schristos     ret = *sel;
4560662d10Schristos     *sel = value;
4660662d10Schristos     return ret;
4760662d10Schristos }
4860662d10Schristos 
4960662d10Schristos /*
50*1dcdf01fSchristos  * Do atomic reference counting. The value 'op' decides what to do.
51*1dcdf01fSchristos  * If it is +1 then the count is incremented.
52*1dcdf01fSchristos  * If |op| is 0, lock is initialised and count is set to 1.
53*1dcdf01fSchristos  * If |op| is -1, count is decremented and the return value is the current
54*1dcdf01fSchristos  * reference count or 0 if no reference count is active.
55*1dcdf01fSchristos  * It returns -1 on initialisation error.
56*1dcdf01fSchristos  * Used by ASN1_SEQUENCE construct of X509, X509_REQ, X509_CRL objects
5760662d10Schristos  */
asn1_do_lock(ASN1_VALUE ** pval,int op,const ASN1_ITEM * it)5860662d10Schristos int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
5960662d10Schristos {
6060662d10Schristos     const ASN1_AUX *aux;
61*1dcdf01fSchristos     CRYPTO_REF_COUNT *lck;
62*1dcdf01fSchristos     CRYPTO_RWLOCK **lock;
63*1dcdf01fSchristos     int ret = -1;
64*1dcdf01fSchristos 
6560662d10Schristos     if ((it->itype != ASN1_ITYPE_SEQUENCE)
6660662d10Schristos         && (it->itype != ASN1_ITYPE_NDEF_SEQUENCE))
6760662d10Schristos         return 0;
6860662d10Schristos     aux = it->funcs;
6960662d10Schristos     if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT))
7060662d10Schristos         return 0;
7160662d10Schristos     lck = offset2ptr(*pval, aux->ref_offset);
72*1dcdf01fSchristos     lock = offset2ptr(*pval, aux->ref_lock);
73*1dcdf01fSchristos 
74*1dcdf01fSchristos     switch (op) {
75*1dcdf01fSchristos     case 0:
76*1dcdf01fSchristos         *lck = ret = 1;
77*1dcdf01fSchristos         *lock = CRYPTO_THREAD_lock_new();
78*1dcdf01fSchristos         if (*lock == NULL) {
79*1dcdf01fSchristos             ASN1err(ASN1_F_ASN1_DO_LOCK, ERR_R_MALLOC_FAILURE);
80*1dcdf01fSchristos             return -1;
8160662d10Schristos         }
82*1dcdf01fSchristos         break;
83*1dcdf01fSchristos     case 1:
84*1dcdf01fSchristos         if (!CRYPTO_UP_REF(lck, &ret, *lock))
85*1dcdf01fSchristos             return -1;
86*1dcdf01fSchristos         break;
87*1dcdf01fSchristos     case -1:
88*1dcdf01fSchristos         if (!CRYPTO_DOWN_REF(lck, &ret, *lock))
89*1dcdf01fSchristos             return -1;  /* failed */
9060662d10Schristos #ifdef REF_PRINT
91*1dcdf01fSchristos         fprintf(stderr, "%p:%4d:%s\n", it, ret, it->sname);
9260662d10Schristos #endif
93*1dcdf01fSchristos         REF_ASSERT_ISNT(ret < 0);
94*1dcdf01fSchristos         if (ret == 0) {
95*1dcdf01fSchristos             CRYPTO_THREAD_lock_free(*lock);
96*1dcdf01fSchristos             *lock = NULL;
97*1dcdf01fSchristos         }
98*1dcdf01fSchristos         break;
99*1dcdf01fSchristos     }
100*1dcdf01fSchristos 
10160662d10Schristos     return ret;
10260662d10Schristos }
10360662d10Schristos 
asn1_get_enc_ptr(ASN1_VALUE ** pval,const ASN1_ITEM * it)10460662d10Schristos static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it)
10560662d10Schristos {
10660662d10Schristos     const ASN1_AUX *aux;
10760662d10Schristos     if (!pval || !*pval)
10860662d10Schristos         return NULL;
10960662d10Schristos     aux = it->funcs;
11060662d10Schristos     if (!aux || !(aux->flags & ASN1_AFLG_ENCODING))
11160662d10Schristos         return NULL;
11260662d10Schristos     return offset2ptr(*pval, aux->enc_offset);
11360662d10Schristos }
11460662d10Schristos 
asn1_enc_init(ASN1_VALUE ** pval,const ASN1_ITEM * it)11560662d10Schristos void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it)
11660662d10Schristos {
11760662d10Schristos     ASN1_ENCODING *enc;
11860662d10Schristos     enc = asn1_get_enc_ptr(pval, it);
11960662d10Schristos     if (enc) {
12060662d10Schristos         enc->enc = NULL;
12160662d10Schristos         enc->len = 0;
12260662d10Schristos         enc->modified = 1;
12360662d10Schristos     }
12460662d10Schristos }
12560662d10Schristos 
asn1_enc_free(ASN1_VALUE ** pval,const ASN1_ITEM * it)12660662d10Schristos void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
12760662d10Schristos {
12860662d10Schristos     ASN1_ENCODING *enc;
12960662d10Schristos     enc = asn1_get_enc_ptr(pval, it);
13060662d10Schristos     if (enc) {
13160662d10Schristos         OPENSSL_free(enc->enc);
13260662d10Schristos         enc->enc = NULL;
13360662d10Schristos         enc->len = 0;
13460662d10Schristos         enc->modified = 1;
13560662d10Schristos     }
13660662d10Schristos }
13760662d10Schristos 
asn1_enc_save(ASN1_VALUE ** pval,const unsigned char * in,int inlen,const ASN1_ITEM * it)13860662d10Schristos int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
13960662d10Schristos                   const ASN1_ITEM *it)
14060662d10Schristos {
14160662d10Schristos     ASN1_ENCODING *enc;
14260662d10Schristos     enc = asn1_get_enc_ptr(pval, it);
14360662d10Schristos     if (!enc)
14460662d10Schristos         return 1;
14560662d10Schristos 
14660662d10Schristos     OPENSSL_free(enc->enc);
147*1dcdf01fSchristos     if ((enc->enc = OPENSSL_malloc(inlen)) == NULL) {
148*1dcdf01fSchristos         ASN1err(ASN1_F_ASN1_ENC_SAVE, ERR_R_MALLOC_FAILURE);
14960662d10Schristos         return 0;
150*1dcdf01fSchristos     }
15160662d10Schristos     memcpy(enc->enc, in, inlen);
15260662d10Schristos     enc->len = inlen;
15360662d10Schristos     enc->modified = 0;
15460662d10Schristos 
15560662d10Schristos     return 1;
15660662d10Schristos }
15760662d10Schristos 
asn1_enc_restore(int * len,unsigned char ** out,ASN1_VALUE ** pval,const ASN1_ITEM * it)15860662d10Schristos int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
15960662d10Schristos                      const ASN1_ITEM *it)
16060662d10Schristos {
16160662d10Schristos     ASN1_ENCODING *enc;
16260662d10Schristos     enc = asn1_get_enc_ptr(pval, it);
16360662d10Schristos     if (!enc || enc->modified)
16460662d10Schristos         return 0;
16560662d10Schristos     if (out) {
16660662d10Schristos         memcpy(*out, enc->enc, enc->len);
16760662d10Schristos         *out += enc->len;
16860662d10Schristos     }
16960662d10Schristos     if (len)
17060662d10Schristos         *len = enc->len;
17160662d10Schristos     return 1;
17260662d10Schristos }
17360662d10Schristos 
17460662d10Schristos /* Given an ASN1_TEMPLATE get a pointer to a field */
asn1_get_field_ptr(ASN1_VALUE ** pval,const ASN1_TEMPLATE * tt)17560662d10Schristos ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
17660662d10Schristos {
17760662d10Schristos     ASN1_VALUE **pvaltmp;
17860662d10Schristos     pvaltmp = offset2ptr(*pval, tt->offset);
17960662d10Schristos     /*
18060662d10Schristos      * NOTE for BOOLEAN types the field is just a plain int so we can't
18160662d10Schristos      * return int **, so settle for (int *).
18260662d10Schristos      */
18360662d10Schristos     return pvaltmp;
18460662d10Schristos }
18560662d10Schristos 
18660662d10Schristos /*
18760662d10Schristos  * Handle ANY DEFINED BY template, find the selector, look up the relevant
18860662d10Schristos  * ASN1_TEMPLATE in the table and return it.
18960662d10Schristos  */
19060662d10Schristos 
asn1_do_adb(ASN1_VALUE ** pval,const ASN1_TEMPLATE * tt,int nullerr)19160662d10Schristos const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
19260662d10Schristos                                  int nullerr)
19360662d10Schristos {
19460662d10Schristos     const ASN1_ADB *adb;
19560662d10Schristos     const ASN1_ADB_TABLE *atbl;
19660662d10Schristos     long selector;
19760662d10Schristos     ASN1_VALUE **sfld;
19860662d10Schristos     int i;
19960662d10Schristos     if (!(tt->flags & ASN1_TFLG_ADB_MASK))
20060662d10Schristos         return tt;
20160662d10Schristos 
20260662d10Schristos     /* Else ANY DEFINED BY ... get the table */
20360662d10Schristos     adb = ASN1_ADB_ptr(tt->item);
20460662d10Schristos 
20560662d10Schristos     /* Get the selector field */
20660662d10Schristos     sfld = offset2ptr(*pval, adb->offset);
20760662d10Schristos 
20860662d10Schristos     /* Check if NULL */
20960662d10Schristos     if (*sfld == NULL) {
21060662d10Schristos         if (!adb->null_tt)
21160662d10Schristos             goto err;
21260662d10Schristos         return adb->null_tt;
21360662d10Schristos     }
21460662d10Schristos 
21560662d10Schristos     /*
21660662d10Schristos      * Convert type to a long: NB: don't check for NID_undef here because it
21760662d10Schristos      * might be a legitimate value in the table
21860662d10Schristos      */
21960662d10Schristos     if (tt->flags & ASN1_TFLG_ADB_OID)
22060662d10Schristos         selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
22160662d10Schristos     else
22260662d10Schristos         selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld);
22360662d10Schristos 
224*1dcdf01fSchristos     /* Let application callback translate value */
225*1dcdf01fSchristos     if (adb->adb_cb != NULL && adb->adb_cb(&selector) == 0) {
226*1dcdf01fSchristos         ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
227*1dcdf01fSchristos         return NULL;
228*1dcdf01fSchristos     }
229*1dcdf01fSchristos 
23060662d10Schristos     /*
23160662d10Schristos      * Try to find matching entry in table Maybe should check application
23260662d10Schristos      * types first to allow application override? Might also be useful to
23360662d10Schristos      * have a flag which indicates table is sorted and we can do a binary
23460662d10Schristos      * search. For now stick to a linear search.
23560662d10Schristos      */
23660662d10Schristos 
23760662d10Schristos     for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++)
23860662d10Schristos         if (atbl->value == selector)
23960662d10Schristos             return &atbl->tt;
24060662d10Schristos 
24160662d10Schristos     /* FIXME: need to search application table too */
24260662d10Schristos 
24360662d10Schristos     /* No match, return default type */
24460662d10Schristos     if (!adb->default_tt)
24560662d10Schristos         goto err;
24660662d10Schristos     return adb->default_tt;
24760662d10Schristos 
24860662d10Schristos  err:
24960662d10Schristos     /* FIXME: should log the value or OID of unsupported type */
25060662d10Schristos     if (nullerr)
25160662d10Schristos         ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
25260662d10Schristos     return NULL;
25360662d10Schristos }
254