Coverage Report

Created: 2024-11-21 07:03

/src/boringssl/crypto/asn1/tasn_enc.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2
 * All rights reserved.
3
 *
4
 * This package is an SSL implementation written
5
 * by Eric Young (eay@cryptsoft.com).
6
 * The implementation was written so as to conform with Netscapes SSL.
7
 *
8
 * This library is free for commercial and non-commercial use as long as
9
 * the following conditions are aheared to.  The following conditions
10
 * apply to all code found in this distribution, be it the RC4, RSA,
11
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12
 * included with this distribution is covered by the same copyright terms
13
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14
 *
15
 * Copyright remains Eric Young's, and as such any Copyright notices in
16
 * the code are not to be removed.
17
 * If this package is used in a product, Eric Young should be given attribution
18
 * as the author of the parts of the library used.
19
 * This can be in the form of a textual message at program startup or
20
 * in documentation (online or textual) provided with the package.
21
 *
22
 * Redistribution and use in source and binary forms, with or without
23
 * modification, are permitted provided that the following conditions
24
 * are met:
25
 * 1. Redistributions of source code must retain the copyright
26
 *    notice, this list of conditions and the following disclaimer.
27
 * 2. Redistributions in binary form must reproduce the above copyright
28
 *    notice, this list of conditions and the following disclaimer in the
29
 *    documentation and/or other materials provided with the distribution.
30
 * 3. All advertising materials mentioning features or use of this software
31
 *    must display the following acknowledgement:
32
 *    "This product includes cryptographic software written by
33
 *     Eric Young (eay@cryptsoft.com)"
34
 *    The word 'cryptographic' can be left out if the rouines from the library
35
 *    being used are not cryptographic related :-).
36
 * 4. If you include any Windows specific code (or a derivative thereof) from
37
 *    the apps directory (application code) you must include an acknowledgement:
38
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50
 * SUCH DAMAGE.
51
 *
52
 * The licence and distribution terms for any publically available version or
53
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
54
 * copied and put under another distribution licence
55
 * [including the GNU Public Licence.] */
56
57
#include <openssl/asn1.h>
58
59
#include <assert.h>
60
#include <limits.h>
61
#include <string.h>
62
63
#include <openssl/asn1t.h>
64
#include <openssl/mem.h>
65
66
#include "../internal.h"
67
#include "internal.h"
68
69
70
static int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
71
                                const ASN1_ITEM *it, int tag, int aclass,
72
                                int optional);
73
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
74
                                 const ASN1_ITEM *it, int tag, int aclass,
75
                                 int optional);
76
static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *out_omit,
77
                       int *putype, const ASN1_ITEM *it);
78
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
79
                            int skcontlen, const ASN1_ITEM *item, int do_sort);
80
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
81
                                const ASN1_TEMPLATE *tt, int tag, int aclass,
82
                                int optional);
83
84
// Top level i2d equivalents
85
86
0
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) {
87
0
  if (out && !*out) {
88
0
    unsigned char *p, *buf;
89
0
    int len = ASN1_item_ex_i2d(&val, NULL, it, /*tag=*/-1, /*aclass=*/0);
90
0
    if (len <= 0) {
91
0
      return len;
92
0
    }
93
0
    buf = OPENSSL_malloc(len);
94
0
    if (!buf) {
95
0
      return -1;
96
0
    }
97
0
    p = buf;
98
0
    int len2 = ASN1_item_ex_i2d(&val, &p, it, /*tag=*/-1, /*aclass=*/0);
99
0
    if (len2 <= 0) {
100
0
      OPENSSL_free(buf);
101
0
      return len2;
102
0
    }
103
0
    assert(len == len2);
104
0
    *out = buf;
105
0
    return len;
106
0
  }
107
108
0
  return ASN1_item_ex_i2d(&val, out, it, /*tag=*/-1, /*aclass=*/0);
109
0
}
110
111
// Encode an item, taking care of IMPLICIT tagging (if any). This function
112
// performs the normal item handling: it can be used in external types.
113
114
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
115
0
                     const ASN1_ITEM *it, int tag, int aclass) {
116
0
  int ret = asn1_item_ex_i2d_opt(pval, out, it, tag, aclass, /*optional=*/0);
117
0
  assert(ret != 0);
118
0
  return ret;
119
0
}
120
121
// asn1_item_ex_i2d_opt behaves like |ASN1_item_ex_i2d| but, if |optional| is
122
// non-zero and |*pval| is omitted, it returns zero and writes no bytes.
123
int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
124
                         const ASN1_ITEM *it, int tag, int aclass,
125
0
                         int optional) {
126
0
  const ASN1_TEMPLATE *tt = NULL;
127
0
  int i, seqcontlen, seqlen;
128
129
  // Historically, |aclass| was repurposed to pass additional flags into the
130
  // encoding process.
131
0
  assert((aclass & ASN1_TFLG_TAG_CLASS) == aclass);
132
  // If not overridding the tag, |aclass| is ignored and should be zero.
133
0
  assert(tag != -1 || aclass == 0);
134
135
  // All fields are pointers, except for boolean |ASN1_ITYPE_PRIMITIVE|s.
136
  // Optional primitives are handled later.
137
0
  if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) {
138
0
    if (optional) {
139
0
      return 0;
140
0
    }
141
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
142
0
    return -1;
143
0
  }
144
145
0
  switch (it->itype) {
146
0
    case ASN1_ITYPE_PRIMITIVE:
147
0
      if (it->templates) {
148
        // This is an |ASN1_ITEM_TEMPLATE|.
149
0
        if (it->templates->flags & ASN1_TFLG_OPTIONAL) {
150
0
          OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
151
0
          return -1;
152
0
        }
153
0
        return asn1_template_ex_i2d(pval, out, it->templates, tag, aclass,
154
0
                                    optional);
155
0
      }
156
0
      return asn1_i2d_ex_primitive(pval, out, it, tag, aclass, optional);
157
158
0
    case ASN1_ITYPE_MSTRING:
159
      // It never makes sense for multi-strings to have implicit tagging, so
160
      // if tag != -1, then this looks like an error in the template.
161
0
      if (tag != -1) {
162
0
        OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
163
0
        return -1;
164
0
      }
165
0
      return asn1_i2d_ex_primitive(pval, out, it, -1, 0, optional);
166
167
0
    case ASN1_ITYPE_CHOICE: {
168
      // It never makes sense for CHOICE types to have implicit tagging, so if
169
      // tag != -1, then this looks like an error in the template.
170
0
      if (tag != -1) {
171
0
        OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
172
0
        return -1;
173
0
      }
174
0
      i = asn1_get_choice_selector(pval, it);
175
0
      if (i < 0 || i >= it->tcount) {
176
0
        OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE);
177
0
        return -1;
178
0
      }
179
0
      const ASN1_TEMPLATE *chtt = it->templates + i;
180
0
      if (chtt->flags & ASN1_TFLG_OPTIONAL) {
181
0
        OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
182
0
        return -1;
183
0
      }
184
0
      ASN1_VALUE **pchval = asn1_get_field_ptr(pval, chtt);
185
0
      return asn1_template_ex_i2d(pchval, out, chtt, -1, 0, /*optional=*/0);
186
0
    }
187
188
0
    case ASN1_ITYPE_EXTERN: {
189
      // We don't support implicit tagging with external types.
190
0
      if (tag != -1) {
191
0
        OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
192
0
        return -1;
193
0
      }
194
0
      const ASN1_EXTERN_FUNCS *ef = it->funcs;
195
0
      int ret = ef->asn1_ex_i2d(pval, out, it);
196
0
      if (ret == 0) {
197
        // |asn1_ex_i2d| should never return zero. We have already checked
198
        // for optional values generically, and |ASN1_ITYPE_EXTERN| fields
199
        // must be pointers.
200
0
        OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
201
0
        return -1;
202
0
      }
203
0
      return ret;
204
0
    }
205
206
0
    case ASN1_ITYPE_SEQUENCE: {
207
0
      i = asn1_enc_restore(&seqcontlen, out, pval, it);
208
      // An error occurred
209
0
      if (i < 0) {
210
0
        return -1;
211
0
      }
212
      // We have a valid cached encoding...
213
0
      if (i > 0) {
214
0
        return seqcontlen;
215
0
      }
216
      // Otherwise carry on
217
0
      seqcontlen = 0;
218
      // If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL
219
0
      if (tag == -1) {
220
0
        tag = V_ASN1_SEQUENCE;
221
0
        aclass = V_ASN1_UNIVERSAL;
222
0
      }
223
      // First work out sequence content length
224
0
      for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
225
0
        const ASN1_TEMPLATE *seqtt;
226
0
        ASN1_VALUE **pseqval;
227
0
        int tmplen;
228
0
        seqtt = asn1_do_adb(pval, tt, 1);
229
0
        if (!seqtt) {
230
0
          return -1;
231
0
        }
232
0
        pseqval = asn1_get_field_ptr(pval, seqtt);
233
0
        tmplen =
234
0
            asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, 0, /*optional=*/0);
235
0
        if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) {
236
0
          return -1;
237
0
        }
238
0
        seqcontlen += tmplen;
239
0
      }
240
241
0
      seqlen = ASN1_object_size(/*constructed=*/1, seqcontlen, tag);
242
0
      if (!out || seqlen == -1) {
243
0
        return seqlen;
244
0
      }
245
      // Output SEQUENCE header
246
0
      ASN1_put_object(out, /*constructed=*/1, seqcontlen, tag, aclass);
247
0
      for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
248
0
        const ASN1_TEMPLATE *seqtt;
249
0
        ASN1_VALUE **pseqval;
250
0
        seqtt = asn1_do_adb(pval, tt, 1);
251
0
        if (!seqtt) {
252
0
          return -1;
253
0
        }
254
0
        pseqval = asn1_get_field_ptr(pval, seqtt);
255
0
        if (asn1_template_ex_i2d(pseqval, out, seqtt, -1, 0, /*optional=*/0) <
256
0
            0) {
257
0
          return -1;
258
0
        }
259
0
      }
260
0
      return seqlen;
261
0
    }
262
263
0
    default:
264
0
      OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
265
0
      return -1;
266
0
  }
267
0
}
268
269
// asn1_template_ex_i2d behaves like |asn1_item_ex_i2d_opt| but uses an
270
// |ASN1_TEMPLATE| instead of an |ASN1_ITEM|. An |ASN1_TEMPLATE| wraps an
271
// |ASN1_ITEM| with modifiers such as tagging, SEQUENCE or SET, etc.
272
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
273
                                const ASN1_TEMPLATE *tt, int tag, int iclass,
274
0
                                int optional) {
275
0
  int i, ret, ttag, tclass;
276
0
  size_t j;
277
0
  uint32_t flags = tt->flags;
278
279
  // Historically, |iclass| was repurposed to pass additional flags into the
280
  // encoding process.
281
0
  assert((iclass & ASN1_TFLG_TAG_CLASS) == iclass);
282
  // If not overridding the tag, |iclass| is ignored and should be zero.
283
0
  assert(tag != -1 || iclass == 0);
284
285
  // Work out tag and class to use: tagging may come either from the
286
  // template or the arguments, not both because this would create
287
  // ambiguity.
288
0
  if (flags & ASN1_TFLG_TAG_MASK) {
289
    // Error if argument and template tagging
290
0
    if (tag != -1) {
291
0
      OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
292
0
      return -1;
293
0
    }
294
    // Get tagging from template
295
0
    ttag = tt->tag;
296
0
    tclass = flags & ASN1_TFLG_TAG_CLASS;
297
0
  } else if (tag != -1) {
298
    // No template tagging, get from arguments
299
0
    ttag = tag;
300
0
    tclass = iclass & ASN1_TFLG_TAG_CLASS;
301
0
  } else {
302
0
    ttag = -1;
303
0
    tclass = 0;
304
0
  }
305
306
  // The template may itself by marked as optional, or this may be the template
307
  // of an |ASN1_ITEM_TEMPLATE| type which was contained inside an outer
308
  // optional template. (They cannot both be true because the
309
  // |ASN1_ITEM_TEMPLATE| codepath rejects optional templates.)
310
0
  assert(!optional || (flags & ASN1_TFLG_OPTIONAL) == 0);
311
0
  optional = optional || (flags & ASN1_TFLG_OPTIONAL) != 0;
312
313
  // At this point 'ttag' contains the outer tag to use, and 'tclass' is the
314
  // class.
315
316
0
  if (flags & ASN1_TFLG_SK_MASK) {
317
    // SET OF, SEQUENCE OF
318
0
    STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
319
0
    int isset, sktag, skaclass;
320
0
    int skcontlen, sklen;
321
0
    ASN1_VALUE *skitem;
322
323
0
    if (!*pval) {
324
0
      if (optional) {
325
0
        return 0;
326
0
      }
327
0
      OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
328
0
      return -1;
329
0
    }
330
331
0
    if (flags & ASN1_TFLG_SET_OF) {
332
0
      isset = 1;
333
      // Historically, types with both bits set were mutated when
334
      // serialized to apply the sort. We no longer support this.
335
0
      assert((flags & ASN1_TFLG_SEQUENCE_OF) == 0);
336
0
    } else {
337
0
      isset = 0;
338
0
    }
339
340
    // Work out inner tag value: if EXPLICIT or no tagging use underlying
341
    // type.
342
0
    if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
343
0
      sktag = ttag;
344
0
      skaclass = tclass;
345
0
    } else {
346
0
      skaclass = V_ASN1_UNIVERSAL;
347
0
      if (isset) {
348
0
        sktag = V_ASN1_SET;
349
0
      } else {
350
0
        sktag = V_ASN1_SEQUENCE;
351
0
      }
352
0
    }
353
354
    // Determine total length of items
355
0
    skcontlen = 0;
356
0
    for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) {
357
0
      int tmplen;
358
0
      skitem = sk_ASN1_VALUE_value(sk, j);
359
0
      tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0);
360
0
      if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) {
361
0
        return -1;
362
0
      }
363
0
      skcontlen += tmplen;
364
0
    }
365
0
    sklen = ASN1_object_size(/*constructed=*/1, skcontlen, sktag);
366
0
    if (sklen == -1) {
367
0
      return -1;
368
0
    }
369
    // If EXPLICIT need length of surrounding tag
370
0
    if (flags & ASN1_TFLG_EXPTAG) {
371
0
      ret = ASN1_object_size(/*constructed=*/1, sklen, ttag);
372
0
    } else {
373
0
      ret = sklen;
374
0
    }
375
376
0
    if (!out || ret == -1) {
377
0
      return ret;
378
0
    }
379
380
    // Now encode this lot...
381
    // EXPLICIT tag
382
0
    if (flags & ASN1_TFLG_EXPTAG) {
383
0
      ASN1_put_object(out, /*constructed=*/1, sklen, ttag, tclass);
384
0
    }
385
    // SET or SEQUENCE and IMPLICIT tag
386
0
    ASN1_put_object(out, /*constructed=*/1, skcontlen, sktag, skaclass);
387
    // And the stuff itself
388
0
    if (!asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset)) {
389
0
      return -1;
390
0
    }
391
0
    return ret;
392
0
  }
393
394
0
  if (flags & ASN1_TFLG_EXPTAG) {
395
    // EXPLICIT tagging
396
    // Find length of tagged item
397
0
    i = asn1_item_ex_i2d_opt(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0,
398
0
                             optional);
399
0
    if (i <= 0) {
400
0
      return i;
401
0
    }
402
    // Find length of EXPLICIT tag
403
0
    ret = ASN1_object_size(/*constructed=*/1, i, ttag);
404
0
    if (out && ret != -1) {
405
      // Output tag and item
406
0
      ASN1_put_object(out, /*constructed=*/1, i, ttag, tclass);
407
0
      if (ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0) < 0) {
408
0
        return -1;
409
0
      }
410
0
    }
411
0
    return ret;
412
0
  }
413
414
  // Either normal or IMPLICIT tagging
415
0
  return asn1_item_ex_i2d_opt(pval, out, ASN1_ITEM_ptr(tt->item), ttag, tclass,
416
0
                              optional);
417
0
}
418
419
// Temporary structure used to hold DER encoding of items for SET OF
420
421
typedef struct {
422
  unsigned char *data;
423
  int length;
424
} DER_ENC;
425
426
0
static int der_cmp(const void *a, const void *b) {
427
0
  const DER_ENC *d1 = a, *d2 = b;
428
0
  int cmplen, i;
429
0
  cmplen = (d1->length < d2->length) ? d1->length : d2->length;
430
0
  i = OPENSSL_memcmp(d1->data, d2->data, cmplen);
431
0
  if (i) {
432
0
    return i;
433
0
  }
434
0
  return d1->length - d2->length;
435
0
}
436
437
// asn1_set_seq_out writes |sk| to |out| under the i2d output convention,
438
// excluding the tag and length. It returns one on success and zero on error.
439
// |skcontlen| must be the total encoded size. If |do_sort| is non-zero, the
440
// elements are sorted for a SET OF type. Each element of |sk| has type
441
// |item|.
442
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
443
0
                            int skcontlen, const ASN1_ITEM *item, int do_sort) {
444
  // No need to sort if there are fewer than two items.
445
0
  if (!do_sort || sk_ASN1_VALUE_num(sk) < 2) {
446
0
    for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
447
0
      ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i);
448
0
      if (ASN1_item_ex_i2d(&skitem, out, item, -1, 0) < 0) {
449
0
        return 0;
450
0
      }
451
0
    }
452
0
    return 1;
453
0
  }
454
455
0
  int ret = 0;
456
0
  unsigned char *const buf = OPENSSL_malloc(skcontlen);
457
0
  DER_ENC *encoded = OPENSSL_calloc(sk_ASN1_VALUE_num(sk), sizeof(*encoded));
458
0
  if (encoded == NULL || buf == NULL) {
459
0
    goto err;
460
0
  }
461
462
  // Encode all the elements into |buf| and populate |encoded|.
463
0
  unsigned char *p = buf;
464
0
  for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
465
0
    ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i);
466
0
    encoded[i].data = p;
467
0
    encoded[i].length = ASN1_item_ex_i2d(&skitem, &p, item, -1, 0);
468
0
    if (encoded[i].length < 0) {
469
0
      goto err;
470
0
    }
471
0
    assert(p - buf <= skcontlen);
472
0
  }
473
474
0
  qsort(encoded, sk_ASN1_VALUE_num(sk), sizeof(*encoded), der_cmp);
475
476
  // Output the elements in sorted order.
477
0
  p = *out;
478
0
  for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
479
0
    OPENSSL_memcpy(p, encoded[i].data, encoded[i].length);
480
0
    p += encoded[i].length;
481
0
  }
482
0
  *out = p;
483
484
0
  ret = 1;
485
486
0
err:
487
0
  OPENSSL_free(encoded);
488
0
  OPENSSL_free(buf);
489
0
  return ret;
490
0
}
491
492
// asn1_i2d_ex_primitive behaves like |ASN1_item_ex_i2d| but |item| must be a
493
// a PRIMITIVE or MSTRING type that is not an |ASN1_ITEM_TEMPLATE|.
494
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
495
                                 const ASN1_ITEM *it, int tag, int aclass,
496
0
                                 int optional) {
497
  // Get length of content octets and maybe find out the underlying type.
498
0
  int omit;
499
0
  int utype = it->utype;
500
0
  int len = asn1_ex_i2c(pval, NULL, &omit, &utype, it);
501
0
  if (len < 0) {
502
0
    return -1;
503
0
  }
504
0
  if (omit) {
505
0
    if (optional) {
506
0
      return 0;
507
0
    }
508
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
509
0
    return -1;
510
0
  }
511
512
  // If SEQUENCE, SET or OTHER then header is included in pseudo content
513
  // octets so don't include tag+length. We need to check here because the
514
  // call to asn1_ex_i2c() could change utype.
515
0
  int usetag =
516
0
      utype != V_ASN1_SEQUENCE && utype != V_ASN1_SET && utype != V_ASN1_OTHER;
517
518
  // If not implicitly tagged get tag from underlying type
519
0
  if (tag == -1) {
520
0
    tag = utype;
521
0
  }
522
523
  // Output tag+length followed by content octets
524
0
  if (out) {
525
0
    if (usetag) {
526
0
      ASN1_put_object(out, /*constructed=*/0, len, tag, aclass);
527
0
    }
528
0
    int len2 = asn1_ex_i2c(pval, *out, &omit, &utype, it);
529
0
    if (len2 < 0) {
530
0
      return -1;
531
0
    }
532
0
    assert(len == len2);
533
0
    assert(!omit);
534
0
    *out += len;
535
0
  }
536
537
0
  if (usetag) {
538
0
    return ASN1_object_size(/*constructed=*/0, len, tag);
539
0
  }
540
0
  return len;
541
0
}
542
543
// asn1_ex_i2c writes the |*pval| to |cout| under the i2d output convention,
544
// excluding the tag and length. It returns the number of bytes written,
545
// possibly zero, on success or -1 on error. If |*pval| should be omitted, it
546
// returns zero and sets |*out_omit| to true.
547
//
548
// If |it| is an MSTRING or ANY type, it gets the underlying type from |*pval|,
549
// which must be an |ASN1_STRING| or |ASN1_TYPE|, respectively. It then updates
550
// |*putype| with the tag number of type used, or |V_ASN1_OTHER| if it was not a
551
// universal type. If |*putype| is set to |V_ASN1_SEQUENCE|, |V_ASN1_SET|, or
552
// |V_ASN1_OTHER|, it additionally outputs the tag and length, so the caller
553
// must not do so.
554
//
555
// Otherwise, |*putype| must contain |it->utype|.
556
//
557
// WARNING: Unlike most functions in this file, |asn1_ex_i2c| can return zero
558
// without omitting the element. ASN.1 values may have empty contents.
559
static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit,
560
0
                       int *putype, const ASN1_ITEM *it) {
561
0
  ASN1_BOOLEAN *tbool = NULL;
562
0
  ASN1_STRING *strtmp;
563
0
  ASN1_OBJECT *otmp;
564
0
  int utype;
565
0
  const unsigned char *cont;
566
0
  unsigned char c;
567
0
  int len;
568
569
  // Historically, |it->funcs| for primitive types contained an
570
  // |ASN1_PRIMITIVE_FUNCS| table of callbacks.
571
0
  assert(it->funcs == NULL);
572
573
0
  *out_omit = 0;
574
575
  // Should type be omitted?
576
0
  if ((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) {
577
0
    if (!*pval) {
578
0
      *out_omit = 1;
579
0
      return 0;
580
0
    }
581
0
  }
582
583
0
  if (it->itype == ASN1_ITYPE_MSTRING) {
584
    // If MSTRING type set the underlying type
585
0
    strtmp = (ASN1_STRING *)*pval;
586
0
    utype = strtmp->type;
587
0
    if (utype < 0 && utype != V_ASN1_OTHER) {
588
      // MSTRINGs can have type -1 when default-constructed.
589
0
      OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
590
0
      return -1;
591
0
    }
592
    // Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values
593
    // that do not match their corresponding utype values. INTEGERs cannot
594
    // participate in MSTRING types, but ENUMERATEDs can.
595
    //
596
    // TODO(davidben): Is this a bug? Although arguably one of the MSTRING
597
    // types should contain more values, rather than less. See
598
    // https://crbug.com/boringssl/412. But it is not possible to fit all
599
    // possible ANY values into an |ASN1_STRING|, so matching the spec here
600
    // is somewhat hopeless.
601
0
    if (utype == V_ASN1_NEG_INTEGER) {
602
0
      utype = V_ASN1_INTEGER;
603
0
    } else if (utype == V_ASN1_NEG_ENUMERATED) {
604
0
      utype = V_ASN1_ENUMERATED;
605
0
    }
606
0
    *putype = utype;
607
0
  } else if (it->utype == V_ASN1_ANY) {
608
    // If ANY set type and pointer to value
609
0
    ASN1_TYPE *typ;
610
0
    typ = (ASN1_TYPE *)*pval;
611
0
    utype = typ->type;
612
0
    if (utype < 0 && utype != V_ASN1_OTHER) {
613
      // |ASN1_TYPE|s can have type -1 when default-constructed.
614
0
      OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
615
0
      return -1;
616
0
    }
617
0
    *putype = utype;
618
0
    pval = &typ->value.asn1_value;
619
0
  } else {
620
0
    utype = *putype;
621
0
  }
622
623
0
  switch (utype) {
624
0
    case V_ASN1_OBJECT:
625
0
      otmp = (ASN1_OBJECT *)*pval;
626
0
      cont = otmp->data;
627
0
      len = otmp->length;
628
0
      if (len == 0) {
629
        // Some |ASN1_OBJECT|s do not have OIDs and cannot be serialized.
630
0
        OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT);
631
0
        return -1;
632
0
      }
633
0
      break;
634
635
0
    case V_ASN1_NULL:
636
0
      cont = NULL;
637
0
      len = 0;
638
0
      break;
639
640
0
    case V_ASN1_BOOLEAN:
641
0
      tbool = (ASN1_BOOLEAN *)pval;
642
0
      if (*tbool == ASN1_BOOLEAN_NONE) {
643
0
        *out_omit = 1;
644
0
        return 0;
645
0
      }
646
0
      if (it->utype != V_ASN1_ANY) {
647
        // Default handling if value == size field then omit
648
0
        if ((*tbool && (it->size > 0)) || (!*tbool && !it->size)) {
649
0
          *out_omit = 1;
650
0
          return 0;
651
0
        }
652
0
      }
653
0
      c = *tbool ? 0xff : 0x00;
654
0
      cont = &c;
655
0
      len = 1;
656
0
      break;
657
658
0
    case V_ASN1_BIT_STRING: {
659
0
      int ret =
660
0
          i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL);
661
      // |i2c_ASN1_BIT_STRING| returns zero on error instead of -1.
662
0
      return ret <= 0 ? -1 : ret;
663
0
    }
664
665
0
    case V_ASN1_INTEGER:
666
0
    case V_ASN1_ENUMERATED: {
667
      // |i2c_ASN1_INTEGER| also handles ENUMERATED.
668
0
      int ret = i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
669
      // |i2c_ASN1_INTEGER| returns zero on error instead of -1.
670
0
      return ret <= 0 ? -1 : ret;
671
0
    }
672
673
0
    case V_ASN1_OCTET_STRING:
674
0
    case V_ASN1_NUMERICSTRING:
675
0
    case V_ASN1_PRINTABLESTRING:
676
0
    case V_ASN1_T61STRING:
677
0
    case V_ASN1_VIDEOTEXSTRING:
678
0
    case V_ASN1_IA5STRING:
679
0
    case V_ASN1_UTCTIME:
680
0
    case V_ASN1_GENERALIZEDTIME:
681
0
    case V_ASN1_GRAPHICSTRING:
682
0
    case V_ASN1_VISIBLESTRING:
683
0
    case V_ASN1_GENERALSTRING:
684
0
    case V_ASN1_UNIVERSALSTRING:
685
0
    case V_ASN1_BMPSTRING:
686
0
    case V_ASN1_UTF8STRING:
687
0
    case V_ASN1_SEQUENCE:
688
0
    case V_ASN1_SET:
689
    // This is not a valid |ASN1_ITEM| type, but it appears in |ASN1_TYPE|.
690
0
    case V_ASN1_OTHER:
691
    // TODO(crbug.com/boringssl/412): This default case should be removed, now
692
    // that we've resolved https://crbug.com/boringssl/561. However, it is still
693
    // needed to support some edge cases in |ASN1_PRINTABLE|. |ASN1_PRINTABLE|
694
    // broadly doesn't tolerate unrecognized universal tags, but except for
695
    // eight values that map to |B_ASN1_UNKNOWN| instead of zero. See the
696
    // X509Test.NameAttributeValues test.
697
0
    default:
698
      // All based on ASN1_STRING and handled the same
699
0
      strtmp = (ASN1_STRING *)*pval;
700
0
      cont = strtmp->data;
701
0
      len = strtmp->length;
702
0
      break;
703
0
  }
704
0
  if (cout && len) {
705
0
    OPENSSL_memcpy(cout, cont, len);
706
0
  }
707
0
  return len;
708
0
}