tasn_enc.c (5c87c606) | tasn_enc.c (3b4e3dcb) |
---|---|
1/* tasn_enc.c */ 2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 3 * project 2000. 4 */ 5/* ==================================================================== | 1/* tasn_enc.c */ 2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 3 * project 2000. 4 */ 5/* ==================================================================== |
6 * Copyright (c) 2000 The OpenSSL Project. All rights reserved. | 6 * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved. |
7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * --- 39 unchanged lines hidden (view full) --- 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59 60#include <stddef.h> 61#include <string.h> | 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * --- 39 unchanged lines hidden (view full) --- 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59 60#include <stddef.h> 61#include <string.h> |
62#include "cryptlib.h" |
|
62#include <openssl/asn1.h> 63#include <openssl/asn1t.h> 64#include <openssl/objects.h> 65 | 63#include <openssl/asn1.h> 64#include <openssl/asn1t.h> 65#include <openssl/objects.h> 66 |
66static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); 67static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *seq, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int isset); | 67static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, 68 const ASN1_ITEM *it, 69 int tag, int aclass); 70static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, 71 int skcontlen, const ASN1_ITEM *item, 72 int do_sort, int iclass); 73static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, 74 const ASN1_TEMPLATE *tt, 75 int tag, int aclass); 76static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, 77 const ASN1_ITEM *it, int flags); |
68 | 78 |
69/* Encode an ASN1 item, this is compatible with the | 79/* Top level i2d equivalents: the 'ndef' variant instructs the encoder 80 * to use indefinite length constructed encoding, where appropriate 81 */ 82 83int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, 84 const ASN1_ITEM *it) 85 { 86 return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF); 87 } 88 89int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) 90 { 91 return asn1_item_flags_i2d(val, out, it, 0); 92 } 93 94/* Encode an ASN1 item, this is use by the |
70 * standard 'i2d' function. 'out' points to | 95 * standard 'i2d' function. 'out' points to |
71 * a buffer to output the data to, in future we will 72 * have more advanced versions that can output data 73 * a piece at a time and this will simply be a special 74 * case. | 96 * a buffer to output the data to. |
75 * 76 * The new i2d has one additional feature. If the output 77 * buffer is NULL (i.e. *out == NULL) then a buffer is 78 * allocated and populated with the encoding. 79 */ 80 | 97 * 98 * The new i2d has one additional feature. If the output 99 * buffer is NULL (i.e. *out == NULL) then a buffer is 100 * allocated and populated with the encoding. 101 */ 102 |
81 82int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) 83{ 84 if(out && !*out) { | 103static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, 104 const ASN1_ITEM *it, int flags) 105 { 106 if (out && !*out) 107 { |
85 unsigned char *p, *buf; 86 int len; | 108 unsigned char *p, *buf; 109 int len; |
87 len = ASN1_item_ex_i2d(&val, NULL, it, -1, 0); 88 if(len <= 0) return len; | 110 len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags); 111 if (len <= 0) 112 return len; |
89 buf = OPENSSL_malloc(len); | 113 buf = OPENSSL_malloc(len); |
90 if(!buf) return -1; | 114 if (!buf) 115 return -1; |
91 p = buf; | 116 p = buf; |
92 ASN1_item_ex_i2d(&val, &p, it, -1, 0); | 117 ASN1_item_ex_i2d(&val, &p, it, -1, flags); |
93 *out = buf; 94 return len; | 118 *out = buf; 119 return len; |
120 } 121 122 return ASN1_item_ex_i2d(&val, out, it, -1, flags); |
|
95 } | 123 } |
96 97 return ASN1_item_ex_i2d(&val, out, it, -1, 0); 98} | |
99 100/* Encode an item, taking care of IMPLICIT tagging (if any). 101 * This function performs the normal item handling: it can be 102 * used in external types. 103 */ 104 | 124 125/* Encode an item, taking care of IMPLICIT tagging (if any). 126 * This function performs the normal item handling: it can be 127 * used in external types. 128 */ 129 |
105int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) 106{ | 130int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, 131 const ASN1_ITEM *it, int tag, int aclass) 132 { |
107 const ASN1_TEMPLATE *tt = NULL; 108 unsigned char *p = NULL; | 133 const ASN1_TEMPLATE *tt = NULL; 134 unsigned char *p = NULL; |
109 int i, seqcontlen, seqlen; 110 ASN1_STRING *strtmp; | 135 int i, seqcontlen, seqlen, ndef = 1; |
111 const ASN1_COMPAT_FUNCS *cf; 112 const ASN1_EXTERN_FUNCS *ef; 113 const ASN1_AUX *aux = it->funcs; | 136 const ASN1_COMPAT_FUNCS *cf; 137 const ASN1_EXTERN_FUNCS *ef; 138 const ASN1_AUX *aux = it->funcs; |
114 ASN1_aux_cb *asn1_cb; 115 if((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) return 0; 116 if(aux && aux->asn1_cb) asn1_cb = aux->asn1_cb; 117 else asn1_cb = 0; | 139 ASN1_aux_cb *asn1_cb = 0; |
118 | 140 |
119 switch(it->itype) { | 141 if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) 142 return 0; |
120 | 143 |
144 if (aux && aux->asn1_cb) 145 asn1_cb = aux->asn1_cb; 146 147 switch(it->itype) 148 { 149 |
|
121 case ASN1_ITYPE_PRIMITIVE: | 150 case ASN1_ITYPE_PRIMITIVE: |
122 if(it->templates) 123 return ASN1_template_i2d(pval, out, it->templates); | 151 if (it->templates) 152 return asn1_template_ex_i2d(pval, out, it->templates, 153 tag, aclass); |
124 return asn1_i2d_ex_primitive(pval, out, it, tag, aclass); 125 break; 126 127 case ASN1_ITYPE_MSTRING: | 154 return asn1_i2d_ex_primitive(pval, out, it, tag, aclass); 155 break; 156 157 case ASN1_ITYPE_MSTRING: |
128 strtmp = (ASN1_STRING *)*pval; 129 return asn1_i2d_ex_primitive(pval, out, it, -1, 0); | 158 return asn1_i2d_ex_primitive(pval, out, it, -1, aclass); |
130 131 case ASN1_ITYPE_CHOICE: | 159 160 case ASN1_ITYPE_CHOICE: |
132 if(asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it)) | 161 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it)) |
133 return 0; 134 i = asn1_get_choice_selector(pval, it); | 162 return 0; 163 i = asn1_get_choice_selector(pval, it); |
135 if((i >= 0) && (i < it->tcount)) { | 164 if ((i >= 0) && (i < it->tcount)) 165 { |
136 ASN1_VALUE **pchval; 137 const ASN1_TEMPLATE *chtt; 138 chtt = it->templates + i; 139 pchval = asn1_get_field_ptr(pval, chtt); | 166 ASN1_VALUE **pchval; 167 const ASN1_TEMPLATE *chtt; 168 chtt = it->templates + i; 169 pchval = asn1_get_field_ptr(pval, chtt); |
140 return ASN1_template_i2d(pchval, out, chtt); 141 } | 170 return asn1_template_ex_i2d(pchval, out, chtt, 171 -1, aclass); 172 } |
142 /* Fixme: error condition if selector out of range */ | 173 /* Fixme: error condition if selector out of range */ |
143 if(asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it)) | 174 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it)) |
144 return 0; 145 break; 146 147 case ASN1_ITYPE_EXTERN: 148 /* If new style i2d it does all the work */ 149 ef = it->funcs; 150 return ef->asn1_ex_i2d(pval, out, it, tag, aclass); 151 152 case ASN1_ITYPE_COMPAT: 153 /* old style hackery... */ 154 cf = it->funcs; | 175 return 0; 176 break; 177 178 case ASN1_ITYPE_EXTERN: 179 /* If new style i2d it does all the work */ 180 ef = it->funcs; 181 return ef->asn1_ex_i2d(pval, out, it, tag, aclass); 182 183 case ASN1_ITYPE_COMPAT: 184 /* old style hackery... */ 185 cf = it->funcs; |
155 if(out) p = *out; | 186 if (out) 187 p = *out; |
156 i = cf->asn1_i2d(*pval, out); 157 /* Fixup for IMPLICIT tag: note this messes up for tags > 30, 158 * but so did the old code. Tags > 30 are very rare anyway. 159 */ | 188 i = cf->asn1_i2d(*pval, out); 189 /* Fixup for IMPLICIT tag: note this messes up for tags > 30, 190 * but so did the old code. Tags > 30 are very rare anyway. 191 */ |
160 if(out && (tag != -1)) | 192 if (out && (tag != -1)) |
161 *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED); 162 return i; 163 | 193 *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED); 194 return i; 195 |
196 case ASN1_ITYPE_NDEF_SEQUENCE: 197 /* Use indefinite length constructed if requested */ 198 if (aclass & ASN1_TFLG_NDEF) ndef = 2; 199 /* fall through */ 200 |
|
164 case ASN1_ITYPE_SEQUENCE: 165 i = asn1_enc_restore(&seqcontlen, out, pval, it); 166 /* An error occurred */ | 201 case ASN1_ITYPE_SEQUENCE: 202 i = asn1_enc_restore(&seqcontlen, out, pval, it); 203 /* An error occurred */ |
167 if(i < 0) return 0; | 204 if (i < 0) 205 return 0; |
168 /* We have a valid cached encoding... */ | 206 /* We have a valid cached encoding... */ |
169 if(i > 0) return seqcontlen; | 207 if (i > 0) 208 return seqcontlen; |
170 /* Otherwise carry on */ 171 seqcontlen = 0; 172 /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ | 209 /* Otherwise carry on */ 210 seqcontlen = 0; 211 /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ |
173 if(tag == -1) { | 212 if (tag == -1) 213 { |
174 tag = V_ASN1_SEQUENCE; | 214 tag = V_ASN1_SEQUENCE; |
175 aclass = V_ASN1_UNIVERSAL; 176 } 177 if(asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it)) | 215 /* Retain any other flags in aclass */ 216 aclass = (aclass & ~ASN1_TFLG_TAG_CLASS) 217 | V_ASN1_UNIVERSAL; 218 } 219 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it)) |
178 return 0; 179 /* First work out sequence content length */ | 220 return 0; 221 /* First work out sequence content length */ |
180 for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) { | 222 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) 223 { |
181 const ASN1_TEMPLATE *seqtt; 182 ASN1_VALUE **pseqval; 183 seqtt = asn1_do_adb(pval, tt, 1); | 224 const ASN1_TEMPLATE *seqtt; 225 ASN1_VALUE **pseqval; 226 seqtt = asn1_do_adb(pval, tt, 1); |
184 if(!seqtt) return 0; | 227 if (!seqtt) 228 return 0; |
185 pseqval = asn1_get_field_ptr(pval, seqtt); 186 /* FIXME: check for errors in enhanced version */ | 229 pseqval = asn1_get_field_ptr(pval, seqtt); 230 /* FIXME: check for errors in enhanced version */ |
187 /* FIXME: special handling of indefinite length encoding */ 188 seqcontlen += ASN1_template_i2d(pseqval, NULL, seqtt); 189 } 190 seqlen = ASN1_object_size(1, seqcontlen, tag); 191 if(!out) return seqlen; | 231 seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt, 232 -1, aclass); 233 } 234 235 seqlen = ASN1_object_size(ndef, seqcontlen, tag); 236 if (!out) 237 return seqlen; |
192 /* Output SEQUENCE header */ | 238 /* Output SEQUENCE header */ |
193 ASN1_put_object(out, 1, seqcontlen, tag, aclass); 194 for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) { | 239 ASN1_put_object(out, ndef, seqcontlen, tag, aclass); 240 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) 241 { |
195 const ASN1_TEMPLATE *seqtt; 196 ASN1_VALUE **pseqval; 197 seqtt = asn1_do_adb(pval, tt, 1); | 242 const ASN1_TEMPLATE *seqtt; 243 ASN1_VALUE **pseqval; 244 seqtt = asn1_do_adb(pval, tt, 1); |
198 if(!seqtt) return 0; | 245 if (!seqtt) 246 return 0; |
199 pseqval = asn1_get_field_ptr(pval, seqtt); 200 /* FIXME: check for errors in enhanced version */ | 247 pseqval = asn1_get_field_ptr(pval, seqtt); 248 /* FIXME: check for errors in enhanced version */ |
201 ASN1_template_i2d(pseqval, out, seqtt); 202 } 203 if(asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it)) | 249 asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass); 250 } 251 if (ndef == 2) 252 ASN1_put_eoc(out); 253 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it)) |
204 return 0; 205 return seqlen; 206 207 default: 208 return 0; | 254 return 0; 255 return seqlen; 256 257 default: 258 return 0; |
209 } | 259 260 } |
210 return 0; | 261 return 0; |
211} | 262 } |
212 | 263 |
213int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt) 214{ 215 int i, ret, flags, aclass; | 264int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, 265 const ASN1_TEMPLATE *tt) 266 { 267 return asn1_template_ex_i2d(pval, out, tt, -1, 0); 268 } 269 270static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, 271 const ASN1_TEMPLATE *tt, int tag, int iclass) 272 { 273 int i, ret, flags, ttag, tclass, ndef; |
216 flags = tt->flags; | 274 flags = tt->flags; |
217 aclass = flags & ASN1_TFLG_TAG_CLASS; 218 if(flags & ASN1_TFLG_SK_MASK) { | 275 /* Work out tag and class to use: tagging may come 276 * either from the template or the arguments, not both 277 * because this would create ambiguity. Additionally 278 * the iclass argument may contain some additional flags 279 * which should be noted and passed down to other levels. 280 */ 281 if (flags & ASN1_TFLG_TAG_MASK) 282 { 283 /* Error if argument and template tagging */ 284 if (tag != -1) 285 /* FIXME: error code here */ 286 return -1; 287 /* Get tagging from template */ 288 ttag = tt->tag; 289 tclass = flags & ASN1_TFLG_TAG_CLASS; 290 } 291 else if (tag != -1) 292 { 293 /* No template tagging, get from arguments */ 294 ttag = tag; 295 tclass = iclass & ASN1_TFLG_TAG_CLASS; 296 } 297 else 298 { 299 ttag = -1; 300 tclass = 0; 301 } 302 /* 303 * Remove any class mask from iflag. 304 */ 305 iclass &= ~ASN1_TFLG_TAG_CLASS; 306 307 /* At this point 'ttag' contains the outer tag to use, 308 * 'tclass' is the class and iclass is any flags passed 309 * to this function. 310 */ 311 312 /* if template and arguments require ndef, use it */ 313 if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF)) 314 ndef = 2; 315 else ndef = 1; 316 317 if (flags & ASN1_TFLG_SK_MASK) 318 { |
219 /* SET OF, SEQUENCE OF */ 220 STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; 221 int isset, sktag, skaclass; 222 int skcontlen, sklen; 223 ASN1_VALUE *skitem; | 319 /* SET OF, SEQUENCE OF */ 320 STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; 321 int isset, sktag, skaclass; 322 int skcontlen, sklen; 323 ASN1_VALUE *skitem; |
224 if(!*pval) return 0; 225 if(flags & ASN1_TFLG_SET_OF) { | 324 325 if (!*pval) 326 return 0; 327 328 if (flags & ASN1_TFLG_SET_OF) 329 { |
226 isset = 1; 227 /* 2 means we reorder */ | 330 isset = 1; 331 /* 2 means we reorder */ |
228 if(flags & ASN1_TFLG_SEQUENCE_OF) isset = 2; 229 } else isset = 0; 230 /* First work out inner tag value */ 231 if(flags & ASN1_TFLG_IMPTAG) { 232 sktag = tt->tag; 233 skaclass = aclass; 234 } else { | 332 if (flags & ASN1_TFLG_SEQUENCE_OF) 333 isset = 2; 334 } 335 else isset = 0; 336 337 /* Work out inner tag value: if EXPLICIT 338 * or no tagging use underlying type. 339 */ 340 if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) 341 { 342 sktag = ttag; 343 skaclass = tclass; 344 } 345 else 346 { |
235 skaclass = V_ASN1_UNIVERSAL; | 347 skaclass = V_ASN1_UNIVERSAL; |
236 if(isset) sktag = V_ASN1_SET; | 348 if (isset) 349 sktag = V_ASN1_SET; |
237 else sktag = V_ASN1_SEQUENCE; | 350 else sktag = V_ASN1_SEQUENCE; |
238 } 239 /* Now work out length of items */ | 351 } 352 353 /* Determine total length of items */ |
240 skcontlen = 0; | 354 skcontlen = 0; |
241 for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) { | 355 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) 356 { |
242 skitem = sk_ASN1_VALUE_value(sk, i); | 357 skitem = sk_ASN1_VALUE_value(sk, i); |
243 skcontlen += ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0); 244 } 245 sklen = ASN1_object_size(1, skcontlen, sktag); | 358 skcontlen += ASN1_item_ex_i2d(&skitem, NULL, 359 ASN1_ITEM_ptr(tt->item), 360 -1, iclass); 361 } 362 sklen = ASN1_object_size(ndef, skcontlen, sktag); |
246 /* If EXPLICIT need length of surrounding tag */ | 363 /* If EXPLICIT need length of surrounding tag */ |
247 if(flags & ASN1_TFLG_EXPTAG) 248 ret = ASN1_object_size(1, sklen, tt->tag); | 364 if (flags & ASN1_TFLG_EXPTAG) 365 ret = ASN1_object_size(ndef, sklen, ttag); |
249 else ret = sklen; 250 | 366 else ret = sklen; 367 |
251 if(!out) return ret; | 368 if (!out) 369 return ret; |
252 253 /* Now encode this lot... */ 254 /* EXPLICIT tag */ | 370 371 /* Now encode this lot... */ 372 /* EXPLICIT tag */ |
255 if(flags & ASN1_TFLG_EXPTAG) 256 ASN1_put_object(out, 1, sklen, tt->tag, aclass); | 373 if (flags & ASN1_TFLG_EXPTAG) 374 ASN1_put_object(out, ndef, sklen, ttag, tclass); |
257 /* SET or SEQUENCE and IMPLICIT tag */ | 375 /* SET or SEQUENCE and IMPLICIT tag */ |
258 ASN1_put_object(out, 1, skcontlen, sktag, skaclass); 259 /* And finally the stuff itself */ 260 asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset); | 376 ASN1_put_object(out, ndef, skcontlen, sktag, skaclass); 377 /* And the stuff itself */ 378 asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), 379 isset, iclass); 380 if (ndef == 2) 381 { 382 ASN1_put_eoc(out); 383 if (flags & ASN1_TFLG_EXPTAG) 384 ASN1_put_eoc(out); 385 } |
261 262 return ret; | 386 387 return ret; |
263 } 264 265 if(flags & ASN1_TFLG_EXPTAG) { | 388 } 389 390 if (flags & ASN1_TFLG_EXPTAG) 391 { |
266 /* EXPLICIT tagging */ 267 /* Find length of tagged item */ | 392 /* EXPLICIT tagging */ 393 /* Find length of tagged item */ |
268 i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0); 269 if(!i) return 0; | 394 i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), 395 -1, iclass); 396 if (!i) 397 return 0; |
270 /* Find length of EXPLICIT tag */ | 398 /* Find length of EXPLICIT tag */ |
271 ret = ASN1_object_size(1, i, tt->tag); 272 if(out) { | 399 ret = ASN1_object_size(ndef, i, ttag); 400 if (out) 401 { |
273 /* Output tag and item */ | 402 /* Output tag and item */ |
274 ASN1_put_object(out, 1, i, tt->tag, aclass); 275 ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0); 276 } | 403 ASN1_put_object(out, ndef, i, ttag, tclass); 404 ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), 405 -1, iclass); 406 if (ndef == 2) 407 ASN1_put_eoc(out); 408 } |
277 return ret; | 409 return ret; |
278 } 279 if(flags & ASN1_TFLG_IMPTAG) { 280 /* IMPLICIT tagging */ 281 return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), tt->tag, aclass); 282 } 283 /* Nothing special: treat as normal */ 284 return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0); | 410 } 411 412 /* Either normal or IMPLICIT tagging: combine class and flags */ 413 return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), 414 ttag, tclass | iclass); 415 |
285} 286 287/* Temporary structure used to hold DER encoding of items for SET OF */ 288 289typedef struct { 290 unsigned char *data; 291 int length; 292 ASN1_VALUE *field; 293} DER_ENC; 294 295static int der_cmp(const void *a, const void *b) | 416} 417 418/* Temporary structure used to hold DER encoding of items for SET OF */ 419 420typedef struct { 421 unsigned char *data; 422 int length; 423 ASN1_VALUE *field; 424} DER_ENC; 425 426static int der_cmp(const void *a, const void *b) |
296{ | 427 { |
297 const DER_ENC *d1 = a, *d2 = b; 298 int cmplen, i; 299 cmplen = (d1->length < d2->length) ? d1->length : d2->length; 300 i = memcmp(d1->data, d2->data, cmplen); | 428 const DER_ENC *d1 = a, *d2 = b; 429 int cmplen, i; 430 cmplen = (d1->length < d2->length) ? d1->length : d2->length; 431 i = memcmp(d1->data, d2->data, cmplen); |
301 if(i) return i; | 432 if (i) 433 return i; |
302 return d1->length - d2->length; | 434 return d1->length - d2->length; |
303} | 435 } |
304 305/* Output the content octets of SET OF or SEQUENCE OF */ 306 | 436 437/* Output the content octets of SET OF or SEQUENCE OF */ 438 |
307static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int do_sort) 308{ | 439static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, 440 int skcontlen, const ASN1_ITEM *item, 441 int do_sort, int iclass) 442 { |
309 int i; 310 ASN1_VALUE *skitem; 311 unsigned char *tmpdat = NULL, *p = NULL; 312 DER_ENC *derlst = NULL, *tder; | 443 int i; 444 ASN1_VALUE *skitem; 445 unsigned char *tmpdat = NULL, *p = NULL; 446 DER_ENC *derlst = NULL, *tder; |
313 if(do_sort) { | 447 if (do_sort) 448 { |
314 /* Don't need to sort less than 2 items */ | 449 /* Don't need to sort less than 2 items */ |
315 if(sk_ASN1_VALUE_num(sk) < 2) do_sort = 0; 316 else { 317 derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) * sizeof(*derlst)); | 450 if (sk_ASN1_VALUE_num(sk) < 2) 451 do_sort = 0; 452 else 453 { 454 derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) 455 * sizeof(*derlst)); |
318 tmpdat = OPENSSL_malloc(skcontlen); | 456 tmpdat = OPENSSL_malloc(skcontlen); |
319 if(!derlst || !tmpdat) return 0; | 457 if (!derlst || !tmpdat) 458 return 0; 459 } |
320 } | 460 } |
321 } | |
322 /* If not sorting just output each item */ | 461 /* If not sorting just output each item */ |
323 if(!do_sort) { 324 for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) { | 462 if (!do_sort) 463 { 464 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) 465 { |
325 skitem = sk_ASN1_VALUE_value(sk, i); | 466 skitem = sk_ASN1_VALUE_value(sk, i); |
326 ASN1_item_i2d(skitem, out, item); 327 } | 467 ASN1_item_ex_i2d(&skitem, out, item, -1, iclass); 468 } |
328 return 1; | 469 return 1; |
329 } | 470 } |
330 p = tmpdat; | 471 p = tmpdat; |
472 |
|
331 /* Doing sort: build up a list of each member's DER encoding */ | 473 /* Doing sort: build up a list of each member's DER encoding */ |
332 for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { | 474 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) 475 { |
333 skitem = sk_ASN1_VALUE_value(sk, i); 334 tder->data = p; | 476 skitem = sk_ASN1_VALUE_value(sk, i); 477 tder->data = p; |
335 tder->length = ASN1_item_i2d(skitem, &p, item); | 478 tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass); |
336 tder->field = skitem; | 479 tder->field = skitem; |
337 } | 480 } 481 |
338 /* Now sort them */ 339 qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); 340 /* Output sorted DER encoding */ 341 p = *out; | 482 /* Now sort them */ 483 qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); 484 /* Output sorted DER encoding */ 485 p = *out; |
342 for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { | 486 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) 487 { |
343 memcpy(p, tder->data, tder->length); 344 p += tder->length; | 488 memcpy(p, tder->data, tder->length); 489 p += tder->length; |
345 } | 490 } |
346 *out = p; 347 /* If do_sort is 2 then reorder the STACK */ | 491 *out = p; 492 /* If do_sort is 2 then reorder the STACK */ |
348 if(do_sort == 2) { 349 for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) | 493 if (do_sort == 2) 494 { 495 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); 496 i++, tder++) |
350 sk_ASN1_VALUE_set(sk, i, tder->field); | 497 sk_ASN1_VALUE_set(sk, i, tder->field); |
351 } | 498 } |
352 OPENSSL_free(derlst); 353 OPENSSL_free(tmpdat); 354 return 1; | 499 OPENSSL_free(derlst); 500 OPENSSL_free(tmpdat); 501 return 1; |
355} | 502 } |
356 | 503 |
357static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) 358{ | 504static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, 505 const ASN1_ITEM *it, int tag, int aclass) 506 { |
359 int len; 360 int utype; 361 int usetag; | 507 int len; 508 int utype; 509 int usetag; |
510 int ndef = 0; |
|
362 363 utype = it->utype; 364 365 /* Get length of content octets and maybe find 366 * out the underlying type. 367 */ 368 369 len = asn1_ex_i2c(pval, NULL, &utype, it); 370 371 /* If SEQUENCE, SET or OTHER then header is 372 * included in pseudo content octets so don't 373 * include tag+length. We need to check here 374 * because the call to asn1_ex_i2c() could change 375 * utype. 376 */ | 511 512 utype = it->utype; 513 514 /* Get length of content octets and maybe find 515 * out the underlying type. 516 */ 517 518 len = asn1_ex_i2c(pval, NULL, &utype, it); 519 520 /* If SEQUENCE, SET or OTHER then header is 521 * included in pseudo content octets so don't 522 * include tag+length. We need to check here 523 * because the call to asn1_ex_i2c() could change 524 * utype. 525 */ |
377 if((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || | 526 if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || |
378 (utype == V_ASN1_OTHER)) 379 usetag = 0; 380 else usetag = 1; 381 382 /* -1 means omit type */ 383 | 527 (utype == V_ASN1_OTHER)) 528 usetag = 0; 529 else usetag = 1; 530 531 /* -1 means omit type */ 532 |
384 if(len == -1) return 0; | 533 if (len == -1) 534 return 0; |
385 | 535 |
536 /* -2 return is special meaning use ndef */ 537 if (len == -2) 538 { 539 ndef = 2; 540 len = 0; 541 } 542 |
|
386 /* If not implicitly tagged get tag from underlying type */ | 543 /* If not implicitly tagged get tag from underlying type */ |
387 if(tag == -1) tag = utype; | 544 if (tag == -1) tag = utype; |
388 389 /* Output tag+length followed by content octets */ | 545 546 /* Output tag+length followed by content octets */ |
390 if(out) { 391 if(usetag) ASN1_put_object(out, 0, len, tag, aclass); | 547 if (out) 548 { 549 if (usetag) 550 ASN1_put_object(out, ndef, len, tag, aclass); |
392 asn1_ex_i2c(pval, *out, &utype, it); | 551 asn1_ex_i2c(pval, *out, &utype, it); |
393 *out += len; 394 } | 552 if (ndef) 553 ASN1_put_eoc(out); 554 else 555 *out += len; 556 } |
395 | 557 |
396 if(usetag) return ASN1_object_size(0, len, tag); | 558 if (usetag) 559 return ASN1_object_size(ndef, len, tag); |
397 return len; | 560 return len; |
398} | 561 } |
399 400/* Produce content octets from a structure */ 401 | 562 563/* Produce content octets from a structure */ 564 |
402int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, const ASN1_ITEM *it) 403{ | 565int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, 566 const ASN1_ITEM *it) 567 { |
404 ASN1_BOOLEAN *tbool = NULL; 405 ASN1_STRING *strtmp; 406 ASN1_OBJECT *otmp; 407 int utype; 408 unsigned char *cont, c; 409 int len; 410 const ASN1_PRIMITIVE_FUNCS *pf; 411 pf = it->funcs; | 568 ASN1_BOOLEAN *tbool = NULL; 569 ASN1_STRING *strtmp; 570 ASN1_OBJECT *otmp; 571 int utype; 572 unsigned char *cont, c; 573 int len; 574 const ASN1_PRIMITIVE_FUNCS *pf; 575 pf = it->funcs; |
412 if(pf && pf->prim_i2c) return pf->prim_i2c(pval, cout, putype, it); | 576 if (pf && pf->prim_i2c) 577 return pf->prim_i2c(pval, cout, putype, it); |
413 414 /* Should type be omitted? */ | 578 579 /* Should type be omitted? */ |
415 if((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) { 416 if(!*pval) return -1; 417 } | 580 if ((it->itype != ASN1_ITYPE_PRIMITIVE) 581 || (it->utype != V_ASN1_BOOLEAN)) 582 { 583 if (!*pval) return -1; 584 } |
418 | 585 |
419 if(it->itype == ASN1_ITYPE_MSTRING) { | 586 if (it->itype == ASN1_ITYPE_MSTRING) 587 { |
420 /* If MSTRING type set the underlying type */ 421 strtmp = (ASN1_STRING *)*pval; 422 utype = strtmp->type; 423 *putype = utype; | 588 /* If MSTRING type set the underlying type */ 589 strtmp = (ASN1_STRING *)*pval; 590 utype = strtmp->type; 591 *putype = utype; |
424 } else if(it->utype == V_ASN1_ANY) { | 592 } 593 else if (it->utype == V_ASN1_ANY) 594 { |
425 /* If ANY set type and pointer to value */ 426 ASN1_TYPE *typ; 427 typ = (ASN1_TYPE *)*pval; 428 utype = typ->type; 429 *putype = utype; 430 pval = (ASN1_VALUE **)&typ->value.ptr; | 595 /* If ANY set type and pointer to value */ 596 ASN1_TYPE *typ; 597 typ = (ASN1_TYPE *)*pval; 598 utype = typ->type; 599 *putype = utype; 600 pval = (ASN1_VALUE **)&typ->value.ptr; |
431 } else utype = *putype; | 601 } 602 else utype = *putype; |
432 | 603 |
433 switch(utype) { | 604 switch(utype) 605 { |
434 case V_ASN1_OBJECT: 435 otmp = (ASN1_OBJECT *)*pval; 436 cont = otmp->data; 437 len = otmp->length; 438 break; 439 440 case V_ASN1_NULL: 441 cont = NULL; 442 len = 0; 443 break; 444 445 case V_ASN1_BOOLEAN: 446 tbool = (ASN1_BOOLEAN *)pval; | 606 case V_ASN1_OBJECT: 607 otmp = (ASN1_OBJECT *)*pval; 608 cont = otmp->data; 609 len = otmp->length; 610 break; 611 612 case V_ASN1_NULL: 613 cont = NULL; 614 len = 0; 615 break; 616 617 case V_ASN1_BOOLEAN: 618 tbool = (ASN1_BOOLEAN *)pval; |
447 if(*tbool == -1) return -1; 448 /* Default handling if value == size field then omit */ 449 if(*tbool && (it->size > 0)) return -1; 450 if(!*tbool && !it->size) return -1; | 619 if (*tbool == -1) 620 return -1; 621 if (it->utype != V_ASN1_ANY) 622 { 623 /* Default handling if value == size field then omit */ 624 if (*tbool && (it->size > 0)) 625 return -1; 626 if (!*tbool && !it->size) 627 return -1; 628 } |
451 c = (unsigned char)*tbool; 452 cont = &c; 453 len = 1; 454 break; 455 456 case V_ASN1_BIT_STRING: | 629 c = (unsigned char)*tbool; 630 cont = &c; 631 len = 1; 632 break; 633 634 case V_ASN1_BIT_STRING: |
457 return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL); | 635 return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, 636 cout ? &cout : NULL); |
458 break; 459 460 case V_ASN1_INTEGER: 461 case V_ASN1_NEG_INTEGER: 462 case V_ASN1_ENUMERATED: 463 case V_ASN1_NEG_ENUMERATED: 464 /* These are all have the same content format 465 * as ASN1_INTEGER 466 */ | 637 break; 638 639 case V_ASN1_INTEGER: 640 case V_ASN1_NEG_INTEGER: 641 case V_ASN1_ENUMERATED: 642 case V_ASN1_NEG_ENUMERATED: 643 /* These are all have the same content format 644 * as ASN1_INTEGER 645 */ |
467 return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); | 646 return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, 647 cout ? &cout : NULL); |
468 break; 469 470 case V_ASN1_OCTET_STRING: 471 case V_ASN1_NUMERICSTRING: 472 case V_ASN1_PRINTABLESTRING: 473 case V_ASN1_T61STRING: 474 case V_ASN1_VIDEOTEXSTRING: 475 case V_ASN1_IA5STRING: --- 5 unchanged lines hidden (view full) --- 481 case V_ASN1_UNIVERSALSTRING: 482 case V_ASN1_BMPSTRING: 483 case V_ASN1_UTF8STRING: 484 case V_ASN1_SEQUENCE: 485 case V_ASN1_SET: 486 default: 487 /* All based on ASN1_STRING and handled the same */ 488 strtmp = (ASN1_STRING *)*pval; | 648 break; 649 650 case V_ASN1_OCTET_STRING: 651 case V_ASN1_NUMERICSTRING: 652 case V_ASN1_PRINTABLESTRING: 653 case V_ASN1_T61STRING: 654 case V_ASN1_VIDEOTEXSTRING: 655 case V_ASN1_IA5STRING: --- 5 unchanged lines hidden (view full) --- 661 case V_ASN1_UNIVERSALSTRING: 662 case V_ASN1_BMPSTRING: 663 case V_ASN1_UTF8STRING: 664 case V_ASN1_SEQUENCE: 665 case V_ASN1_SET: 666 default: 667 /* All based on ASN1_STRING and handled the same */ 668 strtmp = (ASN1_STRING *)*pval; |
669 /* Special handling for NDEF */ 670 if ((it->size == ASN1_TFLG_NDEF) 671 && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) 672 { 673 if (cout) 674 { 675 strtmp->data = cout; 676 strtmp->length = 0; 677 } 678 /* Special return code */ 679 return -2; 680 } |
|
489 cont = strtmp->data; 490 len = strtmp->length; 491 492 break; 493 | 681 cont = strtmp->data; 682 len = strtmp->length; 683 684 break; 685 |
494 } 495 if(cout && len) memcpy(cout, cont, len); | 686 } 687 if (cout && len) 688 memcpy(cout, cont, len); |
496 return len; | 689 return len; |
497} | 690 } |