1 /* 2 * Copyright (c) 1997, 1998, 1999 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.22 1999/12/02 17:05:02 joda 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_general_string (unsigned char *p, size_t len, 225 const general_string *data, size_t *size) 226 { 227 size_t ret = 0; 228 size_t l; 229 int e; 230 231 e = der_put_general_string (p, len, data, &l); 232 if (e) 233 return e; 234 p -= l; 235 len -= l; 236 ret += l; 237 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_GeneralString, &l); 238 if (e) 239 return e; 240 p -= l; 241 len -= l; 242 ret += l; 243 *size = ret; 244 return 0; 245 } 246 247 int 248 encode_octet_string (unsigned char *p, size_t len, 249 const octet_string *k, size_t *size) 250 { 251 size_t ret = 0; 252 size_t l; 253 int e; 254 255 e = der_put_octet_string (p, len, k, &l); 256 if (e) 257 return e; 258 p -= l; 259 len -= l; 260 ret += l; 261 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OctetString, &l); 262 if (e) 263 return e; 264 p -= l; 265 len -= l; 266 ret += l; 267 *size = ret; 268 return 0; 269 } 270 271 void 272 time2generalizedtime (time_t t, octet_string *s) 273 { 274 struct tm *tm; 275 276 s->data = malloc(16); 277 s->length = 15; 278 tm = gmtime (&t); 279 sprintf (s->data, "%04d%02d%02d%02d%02d%02dZ", tm->tm_year + 1900, 280 tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, 281 tm->tm_sec); 282 } 283 284 int 285 encode_generalized_time (unsigned char *p, size_t len, 286 const time_t *t, size_t *size) 287 { 288 size_t ret = 0; 289 size_t l; 290 octet_string k; 291 int e; 292 293 time2generalizedtime (*t, &k); 294 e = der_put_octet_string (p, len, &k, &l); 295 free (k.data); 296 if (e) 297 return e; 298 p -= l; 299 len -= l; 300 ret += l; 301 e = der_put_length_and_tag (p, len, k.length, UNIV, PRIM, 302 UT_GeneralizedTime, &l); 303 if (e) 304 return e; 305 p -= l; 306 len -= l; 307 ret += l; 308 *size = ret; 309 return 0; 310 } 311