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