root/source4/heimdal/lib/asn1/der_put.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. der_put_unsigned
  2. der_put_integer
  3. der_put_length
  4. der_put_boolean
  5. der_put_general_string
  6. der_put_utf8string
  7. der_put_printable_string
  8. der_put_ia5_string
  9. der_put_bmp_string
  10. der_put_universal_string
  11. der_put_visible_string
  12. der_put_octet_string
  13. der_put_heim_integer
  14. der_put_generalized_time
  15. der_put_utctime
  16. der_put_oid
  17. der_put_tag
  18. der_put_length_and_tag
  19. _heim_time2generalizedtime
  20. der_put_bit_string
  21. _heim_der_set_sort

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

/* [<][>][^][v][top][bottom][index][help] */