1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/asn.1/asn1_encode.c */
4 * Copyright 1994, 2008 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
27 /* ASN.1 primitive encoders */
29 #include "asn1_encode.h"
30 #include "asn1_make.h"
33 asn1_encode_boolean(asn1buf *buf, asn1_intmax val, unsigned int *retlen)
35 asn1_error_code retval;
36 unsigned int length = 0;
37 unsigned int partlen = 1;
40 bval = val ? 0xFF : 0x00;
42 retval = asn1buf_insert_octet(buf, bval);
43 if (retval) return retval;
46 retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_BOOLEAN, length, &partlen);
47 if (retval) return retval;
54 static asn1_error_code
55 asn1_encode_integer_internal(asn1buf *buf, asn1_intmax val,
58 asn1_error_code retval;
59 unsigned int length = 0;
65 digit = (int) (valcopy&0xFF);
66 retval = asn1buf_insert_octet(buf,(asn1_octet) digit);
67 if (retval) return retval;
69 valcopy = valcopy >> 8;
70 } while (valcopy != 0 && valcopy != ~0);
72 if ((val > 0) && ((digit&0x80) == 0x80)) { /* make sure the high bit is */
73 retval = asn1buf_insert_octet(buf,0); /* of the proper signed-ness */
74 if (retval) return retval;
76 } else if ((val < 0) && ((digit&0x80) != 0x80)) {
77 retval = asn1buf_insert_octet(buf,0xFF);
78 if (retval) return retval;
88 asn1_encode_integer(asn1buf * buf, asn1_intmax val, unsigned int *retlen)
90 asn1_error_code retval;
91 unsigned int length = 0;
93 retval = asn1_encode_integer_internal(buf, val, &partlen);
94 if (retval) return retval;
97 retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_INTEGER,length, &partlen);
98 if (retval) return retval;
107 asn1_encode_enumerated(asn1buf * buf, long val,
108 unsigned int *retlen)
110 asn1_error_code retval;
111 unsigned int length = 0;
112 unsigned int partlen;
113 retval = asn1_encode_integer_internal(buf, val, &partlen);
114 if (retval) return retval;
117 retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_ENUMERATED,length, &partlen);
118 if (retval) return retval;
127 asn1_encode_unsigned_integer(asn1buf *buf, asn1_uintmax val,
128 unsigned int *retlen)
130 asn1_error_code retval;
131 unsigned int length = 0;
132 unsigned int partlen;
133 unsigned long valcopy;
138 digit = (int) (valcopy&0xFF);
139 retval = asn1buf_insert_octet(buf,(asn1_octet) digit);
140 if (retval) return retval;
142 valcopy = valcopy >> 8;
143 } while (valcopy != 0);
145 if (digit&0x80) { /* make sure the high bit is */
146 retval = asn1buf_insert_octet(buf,0); /* of the proper signed-ness */
147 if (retval) return retval;
151 retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_INTEGER,length, &partlen);
152 if (retval) return retval;
159 static asn1_error_code
160 encode_bytestring_with_tag(asn1buf *buf, unsigned int len,
161 const void *val, int tag,
162 unsigned int *retlen)
164 asn1_error_code retval;
167 if (len > 0 && val == 0) return ASN1_MISSING_FIELD;
168 retval = asn1buf_insert_octetstring(buf, len, val);
169 if (retval) return retval;
170 retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, tag,
172 if (retval) return retval;
174 *retlen = len + length;
179 asn1_encode_oid(asn1buf *buf, unsigned int len, const void *val,
180 unsigned int *retlen)
182 return encode_bytestring_with_tag(buf, len, val, ASN1_OBJECTIDENTIFIER,
187 asn1_encode_octetstring(asn1buf *buf, unsigned int len, const void *val,
188 unsigned int *retlen)
190 return encode_bytestring_with_tag(buf, len, val, ASN1_OCTETSTRING,
195 asn1_error_code asn1_encode_null(asn1buf *buf, int *retlen)
197 asn1_error_code retval;
199 retval = asn1buf_insert_octet(buf,0x00);
200 if (retval) return retval;
201 retval = asn1buf_insert_octet(buf,0x05);
202 if (retval) return retval;
208 asn1_error_code asn1_encode_printablestring(asn1buf *buf, unsigned int len,
209 const char *val, int *retlen)
211 return encode_bytestring_with_tag(buf, len, val, ASN1_PRINTABLESTRING,
215 asn1_error_code asn1_encode_ia5string(asn1buf *buf, unsigned int len,
216 const char *val, int *retlen)
218 return encode_bytestring_with_tag(buf, len, val, ASN1_IA5STRING,
224 asn1_encode_generaltime(asn1buf *buf, time_t val, unsigned int *retlen)
226 struct tm *gtime, gtimebuf;
228 time_t gmt_time = val;
231 * Time encoding: YYYYMMDDhhmmssZ
234 sp = "19700101000000Z";
239 * Sanity check this just to be paranoid, as gmtime can return NULL,
240 * and some bogus implementations might overrun on the sprintf.
243 # ifdef GMTIME_R_RETURNS_INT
244 if (gmtime_r(&gmt_time, >imebuf) != 0)
245 return ASN1_BAD_GMTIME;
247 if (gmtime_r(&gmt_time, >imebuf) == NULL)
248 return ASN1_BAD_GMTIME;
251 gtime = gmtime(&gmt_time);
253 return ASN1_BAD_GMTIME;
254 memcpy(>imebuf, gtime, sizeof(gtimebuf));
258 if (gtime->tm_year > 8099 || gtime->tm_mon > 11 ||
259 gtime->tm_mday > 31 || gtime->tm_hour > 23 ||
260 gtime->tm_min > 59 || gtime->tm_sec > 59)
261 return ASN1_BAD_GMTIME;
262 len = snprintf(s, sizeof(s), "%04d%02d%02d%02d%02d%02dZ",
263 1900+gtime->tm_year, gtime->tm_mon+1,
264 gtime->tm_mday, gtime->tm_hour,
265 gtime->tm_min, gtime->tm_sec);
266 if (SNPRINTF_OVERFLOW(len, sizeof(s)))
267 /* Shouldn't be possible given above tests. */
268 return ASN1_BAD_GMTIME;
272 return encode_bytestring_with_tag(buf, 15, sp, ASN1_GENERALTIME,
277 asn1_encode_generalstring(asn1buf *buf, unsigned int len, const void *val,
278 unsigned int *retlen)
280 return encode_bytestring_with_tag(buf, len, val, ASN1_GENERALSTRING,
285 asn1_encode_bitstring(asn1buf *buf, unsigned int len, const void *val,
286 unsigned int *retlen)
288 asn1_error_code retval;
291 retval = asn1buf_insert_octetstring(buf, len, val);
292 if (retval) return retval;
293 retval = asn1buf_insert_octet(buf, 0);
294 if (retval) return retval;
295 retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_BITSTRING,
297 if (retval) return retval;
298 *retlen = len + 1 + length;
303 asn1_encode_opaque(asn1buf *buf, unsigned int len, const void *val,
304 unsigned int *retlen)
306 asn1_error_code retval;
308 retval = asn1buf_insert_octetstring(buf, len, val);
309 if (retval) return retval;
315 * ASN.1 constructed type encoder engine
317 * Two entry points here:
319 * krb5int_asn1_encode_a_thing: Incrementally adds the partial
320 * encoding of an object to an already-initialized asn1buf.
322 * krb5int_asn1_do_full_encode: Returns a completed encoding, in the
323 * correct byte order, in an allocated krb5_data.
326 #ifdef POINTERS_ARE_ALL_THE_SAME
327 #define LOADPTR(PTR,TYPE) \
328 (*(const void *const *)(PTR))
330 #define LOADPTR(PTR,TYPE) \
331 (assert((TYPE)->loadptr != NULL), (TYPE)->loadptr(PTR))
335 get_nullterm_sequence_len(const void *valp, const struct atype_info *seq)
338 const struct atype_info *a;
339 const void *elt, *eltptr;
343 assert(a->type == atype_ptr);
344 assert(seq->size != 0);
347 eltptr = (const char *) valp + i * seq->size;
348 elt = LOADPTR(eltptr, a);
355 static asn1_error_code
356 encode_sequence_of(asn1buf *buf, int seqlen, const void *val,
357 const struct atype_info *eltinfo,
358 unsigned int *retlen);
360 static asn1_error_code
361 encode_nullterm_sequence_of(asn1buf *buf, const void *val,
362 const struct atype_info *type,
364 unsigned int *retlen)
366 int length = get_nullterm_sequence_len(val, type);
367 if (!can_be_empty && length == 0) return ASN1_MISSING_FIELD;
368 return encode_sequence_of(buf, length, val, type, retlen);
371 static asn1_error_code
372 just_encode_sequence(asn1buf *buf, const void *val,
373 const struct seq_info *seq,
374 unsigned int *retlen);
375 static asn1_error_code
376 encode_a_field(asn1buf *buf, const void *val,
377 const struct field_info *field,
378 unsigned int *retlen);
381 krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val,
382 const struct atype_info *a, unsigned int *retlen)
386 assert(a->enc != NULL);
387 return a->enc(buf, val, retlen);
389 assert(a->seq != NULL);
390 return just_encode_sequence(buf, val, a->seq, retlen);
392 assert(a->basetype != NULL);
393 return krb5int_asn1_encode_a_thing(buf, LOADPTR(val, a),
394 a->basetype, retlen);
396 assert(a->field != NULL);
397 return encode_a_field(buf, val, a->field, retlen);
398 case atype_nullterm_sequence_of:
399 case atype_nonempty_nullterm_sequence_of:
400 assert(a->basetype != NULL);
401 return encode_nullterm_sequence_of(buf, val, a->basetype,
402 a->type == atype_nullterm_sequence_of,
404 case atype_tagged_thing:
406 asn1_error_code retval;
407 unsigned int length, sum = 0;
408 retval = krb5int_asn1_encode_a_thing(buf, val, a->basetype, &length);
409 if (retval) return retval;
411 retval = asn1_make_tag(buf, a->tagtype, a->construction, a->tagval, sum, &length);
412 if (retval) return retval;
418 assert(a->loadint != NULL);
419 return asn1_encode_integer(buf, a->loadint(val), retlen);
421 assert(a->loaduint != NULL);
422 return asn1_encode_unsigned_integer(buf, a->loaduint(val), retlen);
427 assert(a->type > atype_min);
428 assert(a->type < atype_max);
429 assert(a->type != atype_fn_len);
434 static asn1_error_code
435 encode_a_field(asn1buf *buf, const void *val,
436 const struct field_info *field,
437 unsigned int *retlen)
439 asn1_error_code retval;
440 unsigned int sum = 0;
442 if (val == NULL) return ASN1_MISSING_FIELD;
444 switch (field->ftype) {
445 case field_immediate:
449 retval = asn1_encode_integer(buf, (asn1_intmax) field->dataoff,
451 if (retval) return retval;
455 case field_sequenceof_len:
457 const void *dataptr, *lenptr;
460 const struct atype_info *a;
463 * The field holds a pointer to the array of objects. So the
464 * address we compute is a pointer-to-pointer, and that's what
465 * field->atype must help us dereference.
467 dataptr = (const char *)val + field->dataoff;
468 lenptr = (const char *)val + field->lenoff;
469 assert(field->atype->type == atype_ptr);
470 dataptr = LOADPTR(dataptr, field->atype);
471 a = field->atype->basetype;
472 assert(field->lentype != 0);
473 assert(field->lentype->type == atype_int || field->lentype->type == atype_uint);
474 assert(sizeof(int) <= sizeof(asn1_intmax));
475 assert(sizeof(unsigned int) <= sizeof(asn1_uintmax));
476 if (field->lentype->type == atype_int) {
477 asn1_intmax xlen = field->lentype->loadint(lenptr);
480 if ((unsigned int) xlen != (asn1_uintmax) xlen)
482 if ((unsigned int) xlen > INT_MAX)
486 asn1_uintmax xlen = field->lentype->loaduint(lenptr);
487 if ((unsigned int) xlen != xlen)
493 if (slen != 0 && dataptr == NULL)
494 return ASN1_MISSING_FIELD;
495 retval = encode_sequence_of(buf, slen, dataptr, a, &length);
496 if (retval) return retval;
503 const struct atype_info *a;
506 dataptr = (const char *)val + field->dataoff;
509 assert(a->type != atype_fn_len);
510 retval = krb5int_asn1_encode_a_thing(buf, dataptr, a, &length);
519 const void *dataptr, *lenptr;
520 const struct atype_info *a;
524 dataptr = (const char *)val + field->dataoff;
525 lenptr = (const char *)val + field->lenoff;
528 assert(a->type == atype_fn_len);
529 assert(field->lentype != 0);
530 assert(field->lentype->type == atype_int || field->lentype->type == atype_uint);
531 assert(sizeof(int) <= sizeof(asn1_intmax));
532 assert(sizeof(unsigned int) <= sizeof(asn1_uintmax));
533 if (field->lentype->type == atype_int) {
534 asn1_intmax xlen = field->lentype->loadint(lenptr);
537 if ((size_t) xlen != (asn1_uintmax) xlen)
539 slen = (size_t) xlen;
541 asn1_uintmax xlen = field->lentype->loaduint(lenptr);
542 if ((size_t) xlen != xlen)
544 slen = (size_t) xlen;
547 dataptr = LOADPTR(dataptr, a);
548 if (slen == SIZE_MAX)
549 /* Error - negative or out of size_t range. */
551 if (dataptr == NULL && slen != 0)
552 return ASN1_MISSING_FIELD;
554 * Currently our string encoders want "unsigned int" for
557 if (slen != (unsigned int) slen)
559 assert(a->enclen != NULL);
560 retval = a->enclen(buf, (unsigned int) slen, dataptr, &length);
568 assert(field->ftype > field_min);
569 assert(field->ftype < field_max);
570 assert(__LINE__ == 0);
573 if (field->tag >= 0) {
575 retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, field->tag, sum,
586 static asn1_error_code
587 encode_fields(asn1buf *buf, const void *val,
588 const struct field_info *fields, size_t nfields,
589 unsigned int optional,
590 unsigned int *retlen)
593 unsigned int sum = 0;
594 for (i = nfields; i > 0; i--) {
595 const struct field_info *f = fields+i-1;
597 asn1_error_code retval;
602 else if ((1u << f->opt) & optional)
607 retval = encode_a_field(buf, val, f, &length);
608 if (retval) return retval;
616 static asn1_error_code
617 just_encode_sequence(asn1buf *buf, const void *val,
618 const struct seq_info *seq,
619 unsigned int *retlen)
621 const struct field_info *fields = seq->fields;
622 size_t nfields = seq->n_fields;
623 unsigned int optional;
624 asn1_error_code retval;
625 unsigned int sum = 0;
628 optional = seq->optional(val);
631 * In this case, none of the field descriptors should indicate
632 * that we examine any bits of this value.
637 retval = encode_fields(buf, val, fields, nfields, optional, &length);
638 if (retval) return retval;
643 retval = asn1_make_sequence(buf, sum, &length);
644 if (retval) return retval;
651 static asn1_error_code
652 encode_sequence_of(asn1buf *buf, int seqlen, const void *val,
653 const struct atype_info *eltinfo,
654 unsigned int *retlen)
656 asn1_error_code retval;
657 unsigned int sum = 0;
660 for (i = seqlen-1; i >= 0; i--) {
663 const struct atype_info *a = eltinfo;
665 assert(eltinfo->size != 0);
666 eltptr = (const char *)val + i * eltinfo->size;
667 retval = krb5int_asn1_encode_a_thing(buf, eltptr, a, &length);
668 if (retval) return retval;
673 retval = asn1_make_sequence(buf, sum, &length);
674 if (retval) return retval;
682 krb5int_asn1_do_full_encode(const void *rep, krb5_data **code,
683 const struct atype_info *a)
686 asn1_error_code retval;
693 return ASN1_MISSING_FIELD;
695 retval = asn1buf_create(&buf);
699 retval = krb5int_asn1_encode_a_thing(buf, rep, a, &length);
702 retval = asn12krb5_buf(buf, &d);
707 asn1buf_destroy(&buf);