1 /* 2 * Copyright (c) 1997 - 2000 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 "gen_locl.h" 35 36 RCSID("$Id: gen_encode.c,v 1.11 2000/06/19 15:19:08 joda Exp $"); 37 38 static void 39 encode_primitive (const char *typename, const char *name) 40 { 41 fprintf (codefile, 42 "e = encode_%s(p, len, %s, &l);\n" 43 "BACK;\n", 44 typename, 45 name); 46 } 47 48 static void 49 encode_type (const char *name, const Type *t) 50 { 51 switch (t->type) { 52 case TType: 53 #if 0 54 encode_type (name, t->symbol->type); 55 #endif 56 fprintf (codefile, 57 "e = encode_%s(p, len, %s, &l);\n" 58 "BACK;\n", 59 t->symbol->gen_name, name); 60 break; 61 case TInteger: 62 if(t->members == NULL) 63 encode_primitive ("integer", name); 64 else { 65 char *s; 66 asprintf(&s, "(const int*)%s", name); 67 if(s == NULL) 68 errx(1, "out of memory"); 69 encode_primitive ("integer", s); 70 free(s); 71 } 72 break; 73 case TUInteger: 74 encode_primitive ("unsigned", name); 75 break; 76 case TOctetString: 77 encode_primitive ("octet_string", name); 78 break; 79 case TBitString: { 80 Member *m; 81 int pos; 82 int rest; 83 int tag = -1; 84 85 if (t->members == NULL) 86 break; 87 88 fprintf (codefile, "{\n" 89 "unsigned char c = 0;\n"); 90 pos = t->members->prev->val; 91 /* fix for buggy MIT (and OSF?) code */ 92 if (pos > 31) 93 abort (); 94 /* 95 * It seems that if we do not always set pos to 31 here, the MIT 96 * code will do the wrong thing. 97 * 98 * I hate ASN.1 (and DER), but I hate it even more when everybody 99 * has to screw it up differently. 100 */ 101 pos = 31; 102 rest = 7 - (pos % 8); 103 104 for (m = t->members->prev; m && tag != m->val; m = m->prev) { 105 while (m->val / 8 < pos / 8) { 106 fprintf (codefile, 107 "*p-- = c; len--; ret++;\n" 108 "c = 0;\n"); 109 pos -= 8; 110 } 111 fprintf (codefile, 112 "if(%s->%s) c |= 1<<%d;\n", name, m->gen_name, 113 7 - m->val % 8); 114 115 if (tag == -1) 116 tag = m->val; 117 } 118 119 fprintf (codefile, 120 "*p-- = c;\n" 121 "*p-- = %d;\n" 122 "len -= 2;\n" 123 "ret += 2;\n" 124 "}\n\n" 125 "e = der_put_length_and_tag (p, len, ret, UNIV, PRIM," 126 "UT_BitString, &l);\n" 127 "BACK;\n", 128 rest); 129 break; 130 } 131 case TSequence: { 132 Member *m; 133 int tag = -1; 134 135 if (t->members == NULL) 136 break; 137 138 for (m = t->members->prev; m && tag != m->val; m = m->prev) { 139 char *s; 140 141 asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name); 142 if (m->optional) 143 fprintf (codefile, 144 "if(%s)\n", 145 s); 146 #if 1 147 fprintf (codefile, "{\n" 148 "int oldret = ret;\n" 149 "ret = 0;\n"); 150 #endif 151 encode_type (s, m->type); 152 fprintf (codefile, 153 "e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, " 154 "%d, &l);\n" 155 "BACK;\n", 156 m->val); 157 #if 1 158 fprintf (codefile, 159 "ret += oldret;\n" 160 "}\n"); 161 #endif 162 if (tag == -1) 163 tag = m->val; 164 free (s); 165 } 166 fprintf (codefile, 167 "e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l);\n" 168 "BACK;\n"); 169 break; 170 } 171 case TSequenceOf: { 172 char *n; 173 174 fprintf (codefile, 175 "for(i = (%s)->len - 1; i >= 0; --i) {\n" 176 #if 1 177 "int oldret = ret;\n" 178 "ret = 0;\n", 179 #else 180 , 181 #endif 182 name); 183 asprintf (&n, "&(%s)->val[i]", name); 184 encode_type (n, t->subtype); 185 fprintf (codefile, 186 #if 1 187 "ret += oldret;\n" 188 #endif 189 "}\n" 190 "e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l);\n" 191 "BACK;\n"); 192 free (n); 193 break; 194 } 195 case TGeneralizedTime: 196 encode_primitive ("generalized_time", name); 197 break; 198 case TGeneralString: 199 encode_primitive ("general_string", name); 200 break; 201 case TApplication: 202 encode_type (name, t->subtype); 203 fprintf (codefile, 204 "e = der_put_length_and_tag (p, len, ret, APPL, CONS, %d, &l);\n" 205 "BACK;\n", 206 t->application); 207 break; 208 default: 209 abort (); 210 } 211 } 212 213 void 214 generate_type_encode (const Symbol *s) 215 { 216 fprintf (headerfile, 217 "int " 218 "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n", 219 s->gen_name, s->gen_name); 220 221 fprintf (codefile, "#define BACK if (e) return e; p -= l; len -= l; ret += l\n\n"); 222 223 224 fprintf (codefile, "int\n" 225 "encode_%s(unsigned char *p, size_t len," 226 " const %s *data, size_t *size)\n" 227 "{\n", 228 s->gen_name, s->gen_name); 229 230 switch (s->type->type) { 231 case TInteger: 232 case TUInteger: 233 case TOctetString: 234 case TGeneralizedTime: 235 case TGeneralString: 236 case TBitString: 237 case TSequence: 238 case TSequenceOf: 239 case TApplication: 240 case TType: 241 fprintf (codefile, 242 "size_t ret = 0;\n" 243 "size_t l;\n" 244 "int i, e;\n\n"); 245 fprintf(codefile, "i = 0;\n"); /* hack to avoid `unused variable' */ 246 247 encode_type("data", s->type); 248 249 fprintf (codefile, "*size = ret;\n" 250 "return 0;\n"); 251 break; 252 default: 253 abort (); 254 } 255 fprintf (codefile, "}\n\n"); 256 } 257