Path: blob/main/crypto/heimdal/lib/asn1/der_put.c
107437 views
/*1* Copyright (c) 1997-2005 Kungliga Tekniska Högskolan2* (Royal Institute of Technology, Stockholm, Sweden).3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8*9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11*12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* 3. Neither the name of the Institute nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233#include "der_locl.h"3435RCSID("$Id$");3637/*38* All encoding functions take a pointer `p' to first position in39* which to write, from the right, `len' which means the maximum40* number of characters we are able to write. The function returns41* the number of characters written in `size' (if non-NULL).42* The return value is 0 or an error.43*/4445int46der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size)47{48unsigned char *base = p;49unsigned val = *v;5051if (val) {52while (len > 0 && val) {53*p-- = val % 256;54val /= 256;55--len;56}57if (val != 0)58return ASN1_OVERFLOW;59else {60if(p[1] >= 128) {61if(len < 1)62return ASN1_OVERFLOW;63*p-- = 0;64}65*size = base - p;66return 0;67}68} else if (len < 1)69return ASN1_OVERFLOW;70else {71*p = 0;72*size = 1;73return 0;74}75}7677int78der_put_unsigned64 (unsigned char *p, size_t len, const uint64_t *v, size_t *size)79{80unsigned char *base = p;81uint64_t val = *v;8283if (val) {84while (len > 0 && val) {85*p-- = val % 256;86val /= 256;87--len;88}89if (val != 0)90return ASN1_OVERFLOW;91else {92if(p[1] >= 128) {93if(len < 1)94return ASN1_OVERFLOW;95*p-- = 0;96}97*size = base - p;98return 0;99}100} else if (len < 1)101return ASN1_OVERFLOW;102else {103*p = 0;104*size = 1;105return 0;106}107}108109int110der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size)111{112unsigned char *base = p;113int val = *v;114115if(val >= 0) {116do {117if(len < 1)118return ASN1_OVERFLOW;119*p-- = val % 256;120len--;121val /= 256;122} while(val);123if(p[1] >= 128) {124if(len < 1)125return ASN1_OVERFLOW;126*p-- = 0;127len--;128}129} else {130val = ~val;131do {132if(len < 1)133return ASN1_OVERFLOW;134*p-- = ~(val % 256);135len--;136val /= 256;137} while(val);138if(p[1] < 128) {139if(len < 1)140return ASN1_OVERFLOW;141*p-- = 0xff;142len--;143}144}145*size = base - p;146return 0;147}148149int150der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size)151{152unsigned char *base = p;153int64_t val = *v;154155if(val >= 0) {156do {157if(len < 1)158return ASN1_OVERFLOW;159*p-- = val % 256;160len--;161val /= 256;162} while(val);163if(p[1] >= 128) {164if(len < 1)165return ASN1_OVERFLOW;166*p-- = 0;167len--;168}169} else {170val = ~val;171do {172if(len < 1)173return ASN1_OVERFLOW;174*p-- = ~(val % 256);175len--;176val /= 256;177} while(val);178if(p[1] < 128) {179if(len < 1)180return ASN1_OVERFLOW;181*p-- = 0xff;182len--;183}184}185*size = base - p;186return 0;187}188189190int191der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)192{193if (len < 1)194return ASN1_OVERFLOW;195196if (val < 128) {197*p = val;198*size = 1;199} else {200size_t l = 0;201202while(val > 0) {203if(len < 2)204return ASN1_OVERFLOW;205*p-- = val % 256;206val /= 256;207len--;208l++;209}210*p = 0x80 | l;211if(size)212*size = l + 1;213}214return 0;215}216217int218der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size)219{220if(len < 1)221return ASN1_OVERFLOW;222if(*data != 0)223*p = 0xff;224else225*p = 0;226*size = 1;227return 0;228}229230int231der_put_general_string (unsigned char *p, size_t len,232const heim_general_string *str, size_t *size)233{234size_t slen = strlen(*str);235236if (len < slen)237return ASN1_OVERFLOW;238p -= slen;239memcpy (p+1, *str, slen);240*size = slen;241return 0;242}243244int245der_put_utf8string (unsigned char *p, size_t len,246const heim_utf8_string *str, size_t *size)247{248return der_put_general_string(p, len, str, size);249}250251int252der_put_printable_string (unsigned char *p, size_t len,253const heim_printable_string *str, size_t *size)254{255return der_put_octet_string(p, len, str, size);256}257258int259der_put_ia5_string (unsigned char *p, size_t len,260const heim_ia5_string *str, size_t *size)261{262return der_put_octet_string(p, len, str, size);263}264265int266der_put_bmp_string (unsigned char *p, size_t len,267const heim_bmp_string *data, size_t *size)268{269size_t i;270if (len / 2 < data->length)271return ASN1_OVERFLOW;272p -= data->length * 2;273for (i = 0; i < data->length; i++) {274p[1] = (data->data[i] >> 8) & 0xff;275p[2] = data->data[i] & 0xff;276p += 2;277}278if (size) *size = data->length * 2;279return 0;280}281282int283der_put_universal_string (unsigned char *p, size_t len,284const heim_universal_string *data, size_t *size)285{286size_t i;287if (len / 4 < data->length)288return ASN1_OVERFLOW;289p -= data->length * 4;290for (i = 0; i < data->length; i++) {291p[1] = (data->data[i] >> 24) & 0xff;292p[2] = (data->data[i] >> 16) & 0xff;293p[3] = (data->data[i] >> 8) & 0xff;294p[4] = data->data[i] & 0xff;295p += 4;296}297if (size) *size = data->length * 4;298return 0;299}300301int302der_put_visible_string (unsigned char *p, size_t len,303const heim_visible_string *str, size_t *size)304{305return der_put_general_string(p, len, str, size);306}307308int309der_put_octet_string (unsigned char *p, size_t len,310const heim_octet_string *data, size_t *size)311{312if (len < data->length)313return ASN1_OVERFLOW;314p -= data->length;315memcpy (p+1, data->data, data->length);316*size = data->length;317return 0;318}319320int321der_put_heim_integer (unsigned char *p, size_t len,322const heim_integer *data, size_t *size)323{324unsigned char *buf = data->data;325int hibitset = 0;326327if (data->length == 0) {328if (len < 1)329return ASN1_OVERFLOW;330*p-- = 0;331if (size)332*size = 1;333return 0;334}335if (len < data->length)336return ASN1_OVERFLOW;337338len -= data->length;339340if (data->negative) {341int i, carry;342for (i = data->length - 1, carry = 1; i >= 0; i--) {343*p = buf[i] ^ 0xff;344if (carry)345carry = !++*p;346p--;347}348if (p[1] < 128) {349if (len < 1)350return ASN1_OVERFLOW;351*p-- = 0xff;352len--;353hibitset = 1;354}355} else {356p -= data->length;357memcpy(p + 1, buf, data->length);358359if (p[1] >= 128) {360if (len < 1)361return ASN1_OVERFLOW;362p[0] = 0;363len--;364hibitset = 1;365}366}367if (size)368*size = data->length + hibitset;369return 0;370}371372int373der_put_generalized_time (unsigned char *p, size_t len,374const time_t *data, size_t *size)375{376heim_octet_string k;377size_t l;378int e;379380e = _heim_time2generalizedtime (*data, &k, 1);381if (e)382return e;383e = der_put_octet_string(p, len, &k, &l);384free(k.data);385if(e)386return e;387if(size)388*size = l;389return 0;390}391392int393der_put_utctime (unsigned char *p, size_t len,394const time_t *data, size_t *size)395{396heim_octet_string k;397size_t l;398int e;399400e = _heim_time2generalizedtime (*data, &k, 0);401if (e)402return e;403e = der_put_octet_string(p, len, &k, &l);404free(k.data);405if(e)406return e;407if(size)408*size = l;409return 0;410}411412int413der_put_oid (unsigned char *p, size_t len,414const heim_oid *data, size_t *size)415{416unsigned char *base = p;417int n;418419for (n = data->length - 1; n >= 2; --n) {420unsigned u = data->components[n];421422if (len < 1)423return ASN1_OVERFLOW;424*p-- = u % 128;425u /= 128;426--len;427while (u > 0) {428if (len < 1)429return ASN1_OVERFLOW;430*p-- = 128 + u % 128;431u /= 128;432--len;433}434}435if (len < 1)436return ASN1_OVERFLOW;437*p-- = 40 * data->components[0] + data->components[1];438*size = base - p;439return 0;440}441442int443der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,444unsigned int tag, size_t *size)445{446if (tag <= 30) {447if (len < 1)448return ASN1_OVERFLOW;449*p = MAKE_TAG(class, type, tag);450*size = 1;451} else {452size_t ret = 0;453unsigned int continuation = 0;454455do {456if (len < 1)457return ASN1_OVERFLOW;458*p-- = tag % 128 | continuation;459len--;460ret++;461tag /= 128;462continuation = 0x80;463} while(tag > 0);464if (len < 1)465return ASN1_OVERFLOW;466*p-- = MAKE_TAG(class, type, 0x1f);467ret++;468*size = ret;469}470return 0;471}472473int474der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,475Der_class class, Der_type type,476unsigned int tag, size_t *size)477{478size_t ret = 0;479size_t l;480int e;481482e = der_put_length (p, len, len_val, &l);483if(e)484return e;485p -= l;486len -= l;487ret += l;488e = der_put_tag (p, len, class, type, tag, &l);489if(e)490return e;491492ret += l;493*size = ret;494return 0;495}496497int498_heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep)499{500struct tm tm;501const size_t len = gtimep ? 15 : 13;502503s->data = malloc(len + 1);504if (s->data == NULL)505return ENOMEM;506s->length = len;507if (_der_gmtime(t, &tm) == NULL)508return ASN1_BAD_TIMEFORMAT;509if (gtimep)510snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ",511tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,512tm.tm_hour, tm.tm_min, tm.tm_sec);513else514snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ",515tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,516tm.tm_hour, tm.tm_min, tm.tm_sec);517518return 0;519}520521int522der_put_bit_string (unsigned char *p, size_t len,523const heim_bit_string *data, size_t *size)524{525size_t data_size = (data->length + 7) / 8;526if (len < data_size + 1)527return ASN1_OVERFLOW;528p -= data_size + 1;529530memcpy (p+2, data->data, data_size);531if (data->length && (data->length % 8) != 0)532p[1] = 8 - (data->length % 8);533else534p[1] = 0;535*size = data_size + 1;536return 0;537}538539int540_heim_der_set_sort(const void *a1, const void *a2)541{542const struct heim_octet_string *s1 = a1, *s2 = a2;543int ret;544545ret = memcmp(s1->data, s2->data,546s1->length < s2->length ? s1->length : s2->length);547if(ret)548return ret;549return s1->length - s2->length;550}551552553