Home | History | Annotate | Line # | Download | only in asn1
      1 /*	$NetBSD: der_put.c,v 1.3 2023/06/19 21:41:42 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997-2005 Kungliga Tekniska Hgskolan
      5  * (Royal Institute of Technology, Stockholm, Sweden).
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * 3. Neither the name of the Institute nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include "der_locl.h"
     37 
     38 __RCSID("$NetBSD: der_put.c,v 1.3 2023/06/19 21:41:42 christos Exp $");
     39 
     40 /*
     41  * All encoding functions take a pointer `p' to first position in
     42  * which to write, from the right, `len' which means the maximum
     43  * number of characters we are able to write.  The function returns
     44  * the number of characters written in `size' (if non-NULL).
     45  * The return value is 0 or an error.
     46  */
     47 
     48 int
     49 der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size)
     50 {
     51     unsigned char *base = p;
     52     unsigned val = *v;
     53 
     54     if (val) {
     55 	while (len > 0 && val) {
     56 	    *p-- = val % 256;
     57 	    val /= 256;
     58 	    --len;
     59 	}
     60 	if (val != 0)
     61 	    return ASN1_OVERFLOW;
     62 	else {
     63 	    if(p[1] >= 128) {
     64 		if(len < 1)
     65 		    return ASN1_OVERFLOW;
     66 		*p-- = 0;
     67 	    }
     68 	    *size = base - p;
     69 	    return 0;
     70 	}
     71     } else if (len < 1)
     72 	return ASN1_OVERFLOW;
     73     else {
     74 	*p    = 0;
     75 	*size = 1;
     76 	return 0;
     77     }
     78 }
     79 
     80 int
     81 der_put_unsigned64 (unsigned char *p, size_t len, const uint64_t *v, size_t *size)
     82 {
     83     unsigned char *base = p;
     84     uint64_t val = *v;
     85 
     86     if (val) {
     87        while (len > 0 && val) {
     88            *p-- = val % 256;
     89            val /= 256;
     90            --len;
     91        }
     92        if (val != 0)
     93            return ASN1_OVERFLOW;
     94        else {
     95            if(p[1] >= 128) {
     96                if(len < 1)
     97                    return ASN1_OVERFLOW;
     98                *p-- = 0;
     99            }
    100            *size = base - p;
    101            return 0;
    102        }
    103     } else if (len < 1)
    104        return ASN1_OVERFLOW;
    105     else {
    106        *p    = 0;
    107        *size = 1;
    108        return 0;
    109     }
    110 }
    111 
    112 int
    113 der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size)
    114 {
    115     unsigned char *base = p;
    116     int val = *v;
    117 
    118     if(val >= 0) {
    119 	do {
    120 	    if(len < 1)
    121 		return ASN1_OVERFLOW;
    122 	    *p-- = val % 256;
    123 	    len--;
    124 	    val /= 256;
    125 	} while(val);
    126 	if(p[1] >= 128) {
    127 	    if(len < 1)
    128 		return ASN1_OVERFLOW;
    129 	    *p-- = 0;
    130 	    len--;
    131 	}
    132     } else {
    133 	val = ~val;
    134 	do {
    135 	    if(len < 1)
    136 		return ASN1_OVERFLOW;
    137 	    *p-- = ~(val % 256);
    138 	    len--;
    139 	    val /= 256;
    140 	} while(val);
    141 	if(p[1] < 128) {
    142 	    if(len < 1)
    143 		return ASN1_OVERFLOW;
    144 	    *p-- = 0xff;
    145 	    len--;
    146 	}
    147     }
    148     *size = base - p;
    149     return 0;
    150 }
    151 
    152 int
    153 der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size)
    154 {
    155     unsigned char *base = p;
    156     int64_t val = *v;
    157 
    158     if(val >= 0) {
    159        do {
    160            if(len < 1)
    161                return ASN1_OVERFLOW;
    162            *p-- = val % 256;
    163            len--;
    164            val /= 256;
    165        } while(val);
    166        if(p[1] >= 128) {
    167            if(len < 1)
    168                return ASN1_OVERFLOW;
    169            *p-- = 0;
    170            len--;
    171        }
    172     } else {
    173        val = ~val;
    174        do {
    175            if(len < 1)
    176                return ASN1_OVERFLOW;
    177            *p-- = ~(val % 256);
    178            len--;
    179            val /= 256;
    180        } while(val);
    181        if(p[1] < 128) {
    182            if(len < 1)
    183                return ASN1_OVERFLOW;
    184            *p-- = 0xff;
    185            len--;
    186        }
    187     }
    188     *size = base - p;
    189     return 0;
    190 }
    191 
    192 
    193 int
    194 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
    195 {
    196     if (len < 1)
    197 	return ASN1_OVERFLOW;
    198 
    199     if (val < 128) {
    200 	*p = val;
    201 	*size = 1;
    202     } else {
    203 	size_t l = 0;
    204 
    205 	while(val > 0) {
    206 	    if(len < 2)
    207 		return ASN1_OVERFLOW;
    208 	    *p-- = val % 256;
    209 	    val /= 256;
    210 	    len--;
    211 	    l++;
    212 	}
    213 	*p = 0x80 | l;
    214 	if(size)
    215 	    *size = l + 1;
    216     }
    217     return 0;
    218 }
    219 
    220 int
    221 der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size)
    222 {
    223     if(len < 1)
    224 	return ASN1_OVERFLOW;
    225     if(*data != 0)
    226 	*p = 0xff;
    227     else
    228 	*p = 0;
    229     *size = 1;
    230     return 0;
    231 }
    232 
    233 int
    234 der_put_general_string (unsigned char *p, size_t len,
    235 			const heim_general_string *str, size_t *size)
    236 {
    237     size_t slen = strlen(*str);
    238 
    239     if (len < slen)
    240 	return ASN1_OVERFLOW;
    241     p -= slen;
    242     memcpy (p+1, *str, slen);
    243     *size = slen;
    244     return 0;
    245 }
    246 
    247 int
    248 der_put_utf8string (unsigned char *p, size_t len,
    249 		    const heim_utf8_string *str, size_t *size)
    250 {
    251     return der_put_general_string(p, len, str, size);
    252 }
    253 
    254 int
    255 der_put_printable_string (unsigned char *p, size_t len,
    256 			  const heim_printable_string *str, size_t *size)
    257 {
    258     return der_put_octet_string(p, len, str, size);
    259 }
    260 
    261 int
    262 der_put_ia5_string (unsigned char *p, size_t len,
    263 		    const heim_ia5_string *str, size_t *size)
    264 {
    265     return der_put_octet_string(p, len, str, size);
    266 }
    267 
    268 int
    269 der_put_bmp_string (unsigned char *p, size_t len,
    270 		    const heim_bmp_string *data, size_t *size)
    271 {
    272     size_t i;
    273     if (len / 2 < data->length)
    274 	return ASN1_OVERFLOW;
    275     p -= data->length * 2;
    276     for (i = 0; i < data->length; i++) {
    277 	p[1] = (data->data[i] >> 8) & 0xff;
    278 	p[2] = data->data[i] & 0xff;
    279 	p += 2;
    280     }
    281     if (size) *size = data->length * 2;
    282     return 0;
    283 }
    284 
    285 int
    286 der_put_universal_string (unsigned char *p, size_t len,
    287 			  const heim_universal_string *data, size_t *size)
    288 {
    289     size_t i;
    290     if (len / 4 < data->length)
    291 	return ASN1_OVERFLOW;
    292     p -= data->length * 4;
    293     for (i = 0; i < data->length; i++) {
    294 	p[1] = (data->data[i] >> 24) & 0xff;
    295 	p[2] = (data->data[i] >> 16) & 0xff;
    296 	p[3] = (data->data[i] >> 8) & 0xff;
    297 	p[4] = data->data[i] & 0xff;
    298 	p += 4;
    299     }
    300     if (size) *size = data->length * 4;
    301     return 0;
    302 }
    303 
    304 int
    305 der_put_visible_string (unsigned char *p, size_t len,
    306 			 const heim_visible_string *str, size_t *size)
    307 {
    308     return der_put_general_string(p, len, str, size);
    309 }
    310 
    311 int
    312 der_put_octet_string (unsigned char *p, size_t len,
    313 		      const heim_octet_string *data, size_t *size)
    314 {
    315     if (len < data->length)
    316 	return ASN1_OVERFLOW;
    317     p -= data->length;
    318     if (data->length)
    319         memcpy(p+1, data->data, data->length);
    320     *size = data->length;
    321     return 0;
    322 }
    323 
    324 int
    325 der_put_heim_integer (unsigned char *p, size_t len,
    326 		     const heim_integer *data, size_t *size)
    327 {
    328     unsigned char *buf = data->data;
    329     int hibitset = 0;
    330 
    331     if (data->length == 0) {
    332 	if (len < 1)
    333 	    return ASN1_OVERFLOW;
    334 	*p-- = 0;
    335 	if (size)
    336 	    *size = 1;
    337 	return 0;
    338     }
    339     if (len < data->length)
    340 	return ASN1_OVERFLOW;
    341 
    342     len -= data->length;
    343 
    344     if (data->negative) {
    345 	ssize_t i;
    346 	int carry;
    347 
    348         /*
    349          * We represent the parsed integer as a positive value with a
    350          * negativity flag.  But we need to put it on the wire as the shortest
    351          * twos-complement byte sequence possible.  So we're going to negate
    352          * the number as go.
    353          */
    354         if (data->length == 1 && *(unsigned char *)data->data == 1) {
    355             *(p--) = 0xff;
    356         } else {
    357             for (i = data->length - 1, carry = 1; i >= 0; i--) {
    358                 *p = buf[i] ^ 0xff;
    359                 if (carry)
    360                     carry = !++*p;
    361                 p--;
    362             }
    363             if (p[1] < 128) {
    364                 if (len < 1)
    365                     return ASN1_OVERFLOW;
    366                 *p-- = 0xff;
    367                 len--;
    368                 hibitset = 1;
    369             }
    370         }
    371     } else {
    372 	p -= data->length;
    373 	memcpy(p + 1, buf, data->length);
    374 
    375 	if (p[1] >= 128) {
    376 	    if (len < 1)
    377 		return ASN1_OVERFLOW;
    378 	    p[0] = 0;
    379 	    len--;
    380 	    hibitset = 1;
    381 	}
    382     }
    383     if (size)
    384 	*size = data->length + hibitset;
    385     return 0;
    386 }
    387 
    388 int
    389 der_put_generalized_time (unsigned char *p, size_t len,
    390 			  const time_t *data, size_t *size)
    391 {
    392     heim_octet_string k;
    393     size_t l;
    394     int e;
    395 
    396     e = _heim_time2generalizedtime (*data, &k, 1);
    397     if (e)
    398 	return e;
    399     e = der_put_octet_string(p, len, &k, &l);
    400     free(k.data);
    401     if(e)
    402 	return e;
    403     if(size)
    404 	*size = l;
    405     return 0;
    406 }
    407 
    408 int
    409 der_put_utctime (unsigned char *p, size_t len,
    410 		 const time_t *data, size_t *size)
    411 {
    412     heim_octet_string k;
    413     size_t l;
    414     int e;
    415 
    416     e = _heim_time2generalizedtime (*data, &k, 0);
    417     if (e)
    418 	return e;
    419     e = der_put_octet_string(p, len, &k, &l);
    420     free(k.data);
    421     if(e)
    422 	return e;
    423     if(size)
    424 	*size = l;
    425     return 0;
    426 }
    427 
    428 int
    429 der_put_oid (unsigned char *p, size_t len,
    430 	     const heim_oid *data, size_t *size)
    431 {
    432     unsigned char *base = p;
    433     size_t n;
    434 
    435     for (n = data->length - 1; n >= 2; --n) {
    436 	unsigned u = data->components[n];
    437 
    438 	if (len < 1)
    439 	    return ASN1_OVERFLOW;
    440 	*p-- = u % 128;
    441 	u /= 128;
    442 	--len;
    443 	while (u > 0) {
    444 	    if (len < 1)
    445 		return ASN1_OVERFLOW;
    446 	    *p-- = 128 + u % 128;
    447 	    u /= 128;
    448 	    --len;
    449 	}
    450     }
    451     if (len < 1)
    452 	return ASN1_OVERFLOW;
    453     *p-- = 40 * data->components[0] + data->components[1];
    454     *size = base - p;
    455     return 0;
    456 }
    457 
    458 int
    459 der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
    460 	     unsigned int tag, size_t *size)
    461 {
    462     if (tag <= 30) {
    463 	if (len < 1)
    464 	    return ASN1_OVERFLOW;
    465 	*p = MAKE_TAG(class, type, tag);
    466 	*size = 1;
    467     } else {
    468 	size_t ret = 0;
    469 	unsigned int continuation = 0;
    470 
    471 	do {
    472 	    if (len < 1)
    473 		return ASN1_OVERFLOW;
    474 	    *p-- = tag % 128 | continuation;
    475 	    len--;
    476 	    ret++;
    477 	    tag /= 128;
    478 	    continuation = 0x80;
    479 	} while(tag > 0);
    480 	if (len < 1)
    481 	    return ASN1_OVERFLOW;
    482 	*p-- = MAKE_TAG(class, type, 0x1f);
    483 	ret++;
    484 	*size = ret;
    485     }
    486     return 0;
    487 }
    488 
    489 int
    490 der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
    491 			Der_class class, Der_type type,
    492 			unsigned int tag, size_t *size)
    493 {
    494     size_t ret = 0;
    495     size_t l;
    496     int e;
    497 
    498     e = der_put_length (p, len, len_val, &l);
    499     if(e)
    500 	return e;
    501     p -= l;
    502     len -= l;
    503     ret += l;
    504     e = der_put_tag (p, len, class, type, tag, &l);
    505     if(e)
    506 	return e;
    507 
    508     ret += l;
    509     *size = ret;
    510     return 0;
    511 }
    512 
    513 int
    514 _heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep)
    515 {
    516      struct tm tm;
    517      const size_t len = gtimep ? 15 : 13;
    518 
    519      s->data = NULL;
    520      s->length = 0;
    521      if (_der_gmtime(t, &tm) == NULL)
    522 	 return ASN1_BAD_TIMEFORMAT;
    523      s->data = malloc(len + 1);
    524      if (s->data == NULL)
    525 	 return ENOMEM;
    526      s->length = len;
    527      if (gtimep)
    528 	 snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ",
    529 		   tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
    530 		   tm.tm_hour, tm.tm_min, tm.tm_sec);
    531      else
    532 	 snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ",
    533 		   tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
    534 		   tm.tm_hour, tm.tm_min, tm.tm_sec);
    535 
    536      return 0;
    537 }
    538 
    539 int
    540 der_put_bit_string (unsigned char *p, size_t len,
    541 		    const heim_bit_string *data, size_t *size)
    542 {
    543     size_t data_size = (data->length + 7) / 8;
    544     if (len < data_size + 1)
    545 	return ASN1_OVERFLOW;
    546     p -= data_size + 1;
    547 
    548     memcpy (p+2, data->data, data_size);
    549     if (data->length && (data->length % 8) != 0)
    550 	p[1] = 8 - (data->length % 8);
    551     else
    552 	p[1] = 0;
    553     *size = data_size + 1;
    554     return 0;
    555 }
    556 
    557 int
    558 _heim_der_set_sort(const void *a1, const void *a2)
    559 {
    560     const heim_octet_string *s1 = a1, *s2 = a2;
    561     int ret;
    562 
    563     ret = memcmp(s1->data, s2->data,
    564 		 s1->length < s2->length ? s1->length : s2->length);
    565     if(ret)
    566 	return ret;
    567     return (int)(s1->length - s2->length);
    568 }
    569