1 /* 2 * Copyright (c) 1997 - 2001 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: der_put.c,v 1.24 2001/01/29 08:31:27 assar Exp $"); 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 and return an int 42 * indicating how many actually got written, or <0 in case of errors. 43 */ 44 45 static int 46 der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size) 47 { 48 unsigned char *base = p; 49 50 if (val) { 51 while (len > 0 && val) { 52 *p-- = val % 256; 53 val /= 256; 54 --len; 55 } 56 if (val != 0) 57 return ASN1_OVERFLOW; 58 else { 59 *size = base - p; 60 return 0; 61 } 62 } else if (len < 1) 63 return ASN1_OVERFLOW; 64 else { 65 *p = 0; 66 *size = 1; 67 return 0; 68 } 69 } 70 71 int 72 der_put_int (unsigned char *p, size_t len, int val, size_t *size) 73 { 74 unsigned char *base = p; 75 76 if(val >= 0) { 77 do { 78 if(len < 1) 79 return ASN1_OVERFLOW; 80 *p-- = val % 256; 81 len--; 82 val /= 256; 83 } while(val); 84 if(p[1] >= 128) { 85 if(len < 1) 86 return ASN1_OVERFLOW; 87 *p-- = 0; 88 len--; 89 } 90 } else { 91 val = ~val; 92 do { 93 if(len < 1) 94 return ASN1_OVERFLOW; 95 *p-- = ~(val % 256); 96 len--; 97 val /= 256; 98 } while(val); 99 if(p[1] < 128) { 100 if(len < 1) 101 return ASN1_OVERFLOW; 102 *p-- = 0xff; 103 len--; 104 } 105 } 106 *size = base - p; 107 return 0; 108 } 109 110 111 int 112 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) 113 { 114 if (val < 128) { 115 if (len < 1) 116 return ASN1_OVERFLOW; 117 else { 118 *p = val; 119 *size = 1; 120 return 0; 121 } 122 } else { 123 size_t l; 124 int e; 125 126 e = der_put_unsigned (p, len - 1, val, &l); 127 if (e) 128 return e; 129 p -= l; 130 *p = 0x80 | l; 131 *size = l + 1; 132 return 0; 133 } 134 } 135 136 int 137 der_put_general_string (unsigned char *p, size_t len, 138 const general_string *str, size_t *size) 139 { 140 size_t slen = strlen(*str); 141 142 if (len < slen) 143 return ASN1_OVERFLOW; 144 p -= slen; 145 len -= slen; 146 memcpy (p+1, *str, slen); 147 *size = slen; 148 return 0; 149 } 150 151 int 152 der_put_octet_string (unsigned char *p, size_t len, 153 const octet_string *data, size_t *size) 154 { 155 if (len < data->length) 156 return ASN1_OVERFLOW; 157 p -= data->length; 158 len -= data->length; 159 memcpy (p+1, data->data, data->length); 160 *size = data->length; 161 return 0; 162 } 163 164 int 165 der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, 166 int tag, size_t *size) 167 { 168 if (len < 1) 169 return ASN1_OVERFLOW; 170 *p = (class << 6) | (type << 5) | tag; /* XXX */ 171 *size = 1; 172 return 0; 173 } 174 175 int 176 der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, 177 Der_class class, Der_type type, int tag, size_t *size) 178 { 179 size_t ret = 0; 180 size_t l; 181 int e; 182 183 e = der_put_length (p, len, len_val, &l); 184 if(e) 185 return e; 186 p -= l; 187 len -= l; 188 ret += l; 189 e = der_put_tag (p, len, class, type, tag, &l); 190 if(e) 191 return e; 192 p -= l; 193 len -= l; 194 ret += l; 195 *size = ret; 196 return 0; 197 } 198 199 int 200 encode_integer (unsigned char *p, size_t len, const int *data, size_t *size) 201 { 202 int num = *data; 203 size_t ret = 0; 204 size_t l; 205 int e; 206 207 e = der_put_int (p, len, num, &l); 208 if(e) 209 return e; 210 p -= l; 211 len -= l; 212 ret += l; 213 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l); 214 if (e) 215 return e; 216 p -= l; 217 len -= l; 218 ret += l; 219 *size = ret; 220 return 0; 221 } 222 223 int 224 encode_unsigned (unsigned char *p, size_t len, const unsigned *data, 225 size_t *size) 226 { 227 unsigned num = *data; 228 size_t ret = 0; 229 size_t l; 230 int e; 231 232 e = der_put_unsigned (p, len, num, &l); 233 if(e) 234 return e; 235 p -= l; 236 len -= l; 237 ret += l; 238 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l); 239 if (e) 240 return e; 241 p -= l; 242 len -= l; 243 ret += l; 244 *size = ret; 245 return 0; 246 } 247 248 int 249 encode_general_string (unsigned char *p, size_t len, 250 const general_string *data, size_t *size) 251 { 252 size_t ret = 0; 253 size_t l; 254 int e; 255 256 e = der_put_general_string (p, len, data, &l); 257 if (e) 258 return e; 259 p -= l; 260 len -= l; 261 ret += l; 262 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_GeneralString, &l); 263 if (e) 264 return e; 265 p -= l; 266 len -= l; 267 ret += l; 268 *size = ret; 269 return 0; 270 } 271 272 int 273 encode_octet_string (unsigned char *p, size_t len, 274 const octet_string *k, size_t *size) 275 { 276 size_t ret = 0; 277 size_t l; 278 int e; 279 280 e = der_put_octet_string (p, len, k, &l); 281 if (e) 282 return e; 283 p -= l; 284 len -= l; 285 ret += l; 286 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OctetString, &l); 287 if (e) 288 return e; 289 p -= l; 290 len -= l; 291 ret += l; 292 *size = ret; 293 return 0; 294 } 295 296 int 297 time2generalizedtime (time_t t, octet_string *s) 298 { 299 struct tm *tm; 300 301 s->data = malloc(16); 302 if (s->data == NULL) 303 return ENOMEM; 304 s->length = 15; 305 tm = gmtime (&t); 306 sprintf (s->data, "%04d%02d%02d%02d%02d%02dZ", tm->tm_year + 1900, 307 tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, 308 tm->tm_sec); 309 return 0; 310 } 311 312 int 313 encode_generalized_time (unsigned char *p, size_t len, 314 const time_t *t, size_t *size) 315 { 316 size_t ret = 0; 317 size_t l; 318 octet_string k; 319 int e; 320 321 e = time2generalizedtime (*t, &k); 322 if (e) 323 return e; 324 e = der_put_octet_string (p, len, &k, &l); 325 free (k.data); 326 if (e) 327 return e; 328 p -= l; 329 len -= l; 330 ret += l; 331 e = der_put_length_and_tag (p, len, k.length, UNIV, PRIM, 332 UT_GeneralizedTime, &l); 333 if (e) 334 return e; 335 p -= l; 336 len -= l; 337 ret += l; 338 *size = ret; 339 return 0; 340 } 341