1*0Sstevel@tonic-gate /* tasn_enc.c */ 2*0Sstevel@tonic-gate /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 3*0Sstevel@tonic-gate * project 2000. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate /* ==================================================================== 6*0Sstevel@tonic-gate * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 7*0Sstevel@tonic-gate * 8*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 9*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 10*0Sstevel@tonic-gate * are met: 11*0Sstevel@tonic-gate * 12*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 13*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 14*0Sstevel@tonic-gate * 15*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 16*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in 17*0Sstevel@tonic-gate * the documentation and/or other materials provided with the 18*0Sstevel@tonic-gate * distribution. 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this 21*0Sstevel@tonic-gate * software must display the following acknowledgment: 22*0Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 23*0Sstevel@tonic-gate * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24*0Sstevel@tonic-gate * 25*0Sstevel@tonic-gate * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26*0Sstevel@tonic-gate * endorse or promote products derived from this software without 27*0Sstevel@tonic-gate * prior written permission. For written permission, please contact 28*0Sstevel@tonic-gate * licensing@OpenSSL.org. 29*0Sstevel@tonic-gate * 30*0Sstevel@tonic-gate * 5. Products derived from this software may not be called "OpenSSL" 31*0Sstevel@tonic-gate * nor may "OpenSSL" appear in their names without prior written 32*0Sstevel@tonic-gate * permission of the OpenSSL Project. 33*0Sstevel@tonic-gate * 34*0Sstevel@tonic-gate * 6. Redistributions of any form whatsoever must retain the following 35*0Sstevel@tonic-gate * acknowledgment: 36*0Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 37*0Sstevel@tonic-gate * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38*0Sstevel@tonic-gate * 39*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40*0Sstevel@tonic-gate * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42*0Sstevel@tonic-gate * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43*0Sstevel@tonic-gate * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44*0Sstevel@tonic-gate * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45*0Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46*0Sstevel@tonic-gate * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48*0Sstevel@tonic-gate * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49*0Sstevel@tonic-gate * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50*0Sstevel@tonic-gate * OF THE POSSIBILITY OF SUCH DAMAGE. 51*0Sstevel@tonic-gate * ==================================================================== 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * This product includes cryptographic software written by Eric Young 54*0Sstevel@tonic-gate * (eay@cryptsoft.com). This product includes software written by Tim 55*0Sstevel@tonic-gate * Hudson (tjh@cryptsoft.com). 56*0Sstevel@tonic-gate * 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate #include <stddef.h> 61*0Sstevel@tonic-gate #include <string.h> 62*0Sstevel@tonic-gate #include <openssl/asn1.h> 63*0Sstevel@tonic-gate #include <openssl/asn1t.h> 64*0Sstevel@tonic-gate #include <openssl/objects.h> 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); 67*0Sstevel@tonic-gate static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *seq, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int isset); 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* Encode an ASN1 item, this is compatible with the 70*0Sstevel@tonic-gate * standard 'i2d' function. 'out' points to 71*0Sstevel@tonic-gate * a buffer to output the data to, in future we will 72*0Sstevel@tonic-gate * have more advanced versions that can output data 73*0Sstevel@tonic-gate * a piece at a time and this will simply be a special 74*0Sstevel@tonic-gate * case. 75*0Sstevel@tonic-gate * 76*0Sstevel@tonic-gate * The new i2d has one additional feature. If the output 77*0Sstevel@tonic-gate * buffer is NULL (i.e. *out == NULL) then a buffer is 78*0Sstevel@tonic-gate * allocated and populated with the encoding. 79*0Sstevel@tonic-gate */ 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) 83*0Sstevel@tonic-gate { 84*0Sstevel@tonic-gate if(out && !*out) { 85*0Sstevel@tonic-gate unsigned char *p, *buf; 86*0Sstevel@tonic-gate int len; 87*0Sstevel@tonic-gate len = ASN1_item_ex_i2d(&val, NULL, it, -1, 0); 88*0Sstevel@tonic-gate if(len <= 0) return len; 89*0Sstevel@tonic-gate buf = OPENSSL_malloc(len); 90*0Sstevel@tonic-gate if(!buf) return -1; 91*0Sstevel@tonic-gate p = buf; 92*0Sstevel@tonic-gate ASN1_item_ex_i2d(&val, &p, it, -1, 0); 93*0Sstevel@tonic-gate *out = buf; 94*0Sstevel@tonic-gate return len; 95*0Sstevel@tonic-gate } 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate return ASN1_item_ex_i2d(&val, out, it, -1, 0); 98*0Sstevel@tonic-gate } 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate /* Encode an item, taking care of IMPLICIT tagging (if any). 101*0Sstevel@tonic-gate * This function performs the normal item handling: it can be 102*0Sstevel@tonic-gate * used in external types. 103*0Sstevel@tonic-gate */ 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) 106*0Sstevel@tonic-gate { 107*0Sstevel@tonic-gate const ASN1_TEMPLATE *tt = NULL; 108*0Sstevel@tonic-gate unsigned char *p = NULL; 109*0Sstevel@tonic-gate int i, seqcontlen, seqlen; 110*0Sstevel@tonic-gate ASN1_STRING *strtmp; 111*0Sstevel@tonic-gate const ASN1_COMPAT_FUNCS *cf; 112*0Sstevel@tonic-gate const ASN1_EXTERN_FUNCS *ef; 113*0Sstevel@tonic-gate const ASN1_AUX *aux = it->funcs; 114*0Sstevel@tonic-gate ASN1_aux_cb *asn1_cb; 115*0Sstevel@tonic-gate if((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) return 0; 116*0Sstevel@tonic-gate if(aux && aux->asn1_cb) asn1_cb = aux->asn1_cb; 117*0Sstevel@tonic-gate else asn1_cb = 0; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate switch(it->itype) { 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate case ASN1_ITYPE_PRIMITIVE: 122*0Sstevel@tonic-gate if(it->templates) 123*0Sstevel@tonic-gate return ASN1_template_i2d(pval, out, it->templates); 124*0Sstevel@tonic-gate return asn1_i2d_ex_primitive(pval, out, it, tag, aclass); 125*0Sstevel@tonic-gate break; 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate case ASN1_ITYPE_MSTRING: 128*0Sstevel@tonic-gate strtmp = (ASN1_STRING *)*pval; 129*0Sstevel@tonic-gate return asn1_i2d_ex_primitive(pval, out, it, -1, 0); 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate case ASN1_ITYPE_CHOICE: 132*0Sstevel@tonic-gate if(asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it)) 133*0Sstevel@tonic-gate return 0; 134*0Sstevel@tonic-gate i = asn1_get_choice_selector(pval, it); 135*0Sstevel@tonic-gate if((i >= 0) && (i < it->tcount)) { 136*0Sstevel@tonic-gate ASN1_VALUE **pchval; 137*0Sstevel@tonic-gate const ASN1_TEMPLATE *chtt; 138*0Sstevel@tonic-gate chtt = it->templates + i; 139*0Sstevel@tonic-gate pchval = asn1_get_field_ptr(pval, chtt); 140*0Sstevel@tonic-gate return ASN1_template_i2d(pchval, out, chtt); 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate /* Fixme: error condition if selector out of range */ 143*0Sstevel@tonic-gate if(asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it)) 144*0Sstevel@tonic-gate return 0; 145*0Sstevel@tonic-gate break; 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate case ASN1_ITYPE_EXTERN: 148*0Sstevel@tonic-gate /* If new style i2d it does all the work */ 149*0Sstevel@tonic-gate ef = it->funcs; 150*0Sstevel@tonic-gate return ef->asn1_ex_i2d(pval, out, it, tag, aclass); 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate case ASN1_ITYPE_COMPAT: 153*0Sstevel@tonic-gate /* old style hackery... */ 154*0Sstevel@tonic-gate cf = it->funcs; 155*0Sstevel@tonic-gate if(out) p = *out; 156*0Sstevel@tonic-gate i = cf->asn1_i2d(*pval, out); 157*0Sstevel@tonic-gate /* Fixup for IMPLICIT tag: note this messes up for tags > 30, 158*0Sstevel@tonic-gate * but so did the old code. Tags > 30 are very rare anyway. 159*0Sstevel@tonic-gate */ 160*0Sstevel@tonic-gate if(out && (tag != -1)) 161*0Sstevel@tonic-gate *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED); 162*0Sstevel@tonic-gate return i; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate case ASN1_ITYPE_SEQUENCE: 165*0Sstevel@tonic-gate i = asn1_enc_restore(&seqcontlen, out, pval, it); 166*0Sstevel@tonic-gate /* An error occurred */ 167*0Sstevel@tonic-gate if(i < 0) return 0; 168*0Sstevel@tonic-gate /* We have a valid cached encoding... */ 169*0Sstevel@tonic-gate if(i > 0) return seqcontlen; 170*0Sstevel@tonic-gate /* Otherwise carry on */ 171*0Sstevel@tonic-gate seqcontlen = 0; 172*0Sstevel@tonic-gate /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ 173*0Sstevel@tonic-gate if(tag == -1) { 174*0Sstevel@tonic-gate tag = V_ASN1_SEQUENCE; 175*0Sstevel@tonic-gate aclass = V_ASN1_UNIVERSAL; 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate if(asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it)) 178*0Sstevel@tonic-gate return 0; 179*0Sstevel@tonic-gate /* First work out sequence content length */ 180*0Sstevel@tonic-gate for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) { 181*0Sstevel@tonic-gate const ASN1_TEMPLATE *seqtt; 182*0Sstevel@tonic-gate ASN1_VALUE **pseqval; 183*0Sstevel@tonic-gate seqtt = asn1_do_adb(pval, tt, 1); 184*0Sstevel@tonic-gate if(!seqtt) return 0; 185*0Sstevel@tonic-gate pseqval = asn1_get_field_ptr(pval, seqtt); 186*0Sstevel@tonic-gate /* FIXME: check for errors in enhanced version */ 187*0Sstevel@tonic-gate /* FIXME: special handling of indefinite length encoding */ 188*0Sstevel@tonic-gate seqcontlen += ASN1_template_i2d(pseqval, NULL, seqtt); 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate seqlen = ASN1_object_size(1, seqcontlen, tag); 191*0Sstevel@tonic-gate if(!out) return seqlen; 192*0Sstevel@tonic-gate /* Output SEQUENCE header */ 193*0Sstevel@tonic-gate ASN1_put_object(out, 1, seqcontlen, tag, aclass); 194*0Sstevel@tonic-gate for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) { 195*0Sstevel@tonic-gate const ASN1_TEMPLATE *seqtt; 196*0Sstevel@tonic-gate ASN1_VALUE **pseqval; 197*0Sstevel@tonic-gate seqtt = asn1_do_adb(pval, tt, 1); 198*0Sstevel@tonic-gate if(!seqtt) return 0; 199*0Sstevel@tonic-gate pseqval = asn1_get_field_ptr(pval, seqtt); 200*0Sstevel@tonic-gate /* FIXME: check for errors in enhanced version */ 201*0Sstevel@tonic-gate ASN1_template_i2d(pseqval, out, seqtt); 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate if(asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it)) 204*0Sstevel@tonic-gate return 0; 205*0Sstevel@tonic-gate return seqlen; 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate default: 208*0Sstevel@tonic-gate return 0; 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate return 0; 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt) 214*0Sstevel@tonic-gate { 215*0Sstevel@tonic-gate int i, ret, flags, aclass; 216*0Sstevel@tonic-gate flags = tt->flags; 217*0Sstevel@tonic-gate aclass = flags & ASN1_TFLG_TAG_CLASS; 218*0Sstevel@tonic-gate if(flags & ASN1_TFLG_SK_MASK) { 219*0Sstevel@tonic-gate /* SET OF, SEQUENCE OF */ 220*0Sstevel@tonic-gate STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; 221*0Sstevel@tonic-gate int isset, sktag, skaclass; 222*0Sstevel@tonic-gate int skcontlen, sklen; 223*0Sstevel@tonic-gate ASN1_VALUE *skitem; 224*0Sstevel@tonic-gate if(!*pval) return 0; 225*0Sstevel@tonic-gate if(flags & ASN1_TFLG_SET_OF) { 226*0Sstevel@tonic-gate isset = 1; 227*0Sstevel@tonic-gate /* 2 means we reorder */ 228*0Sstevel@tonic-gate if(flags & ASN1_TFLG_SEQUENCE_OF) isset = 2; 229*0Sstevel@tonic-gate } else isset = 0; 230*0Sstevel@tonic-gate /* First work out inner tag value */ 231*0Sstevel@tonic-gate if(flags & ASN1_TFLG_IMPTAG) { 232*0Sstevel@tonic-gate sktag = tt->tag; 233*0Sstevel@tonic-gate skaclass = aclass; 234*0Sstevel@tonic-gate } else { 235*0Sstevel@tonic-gate skaclass = V_ASN1_UNIVERSAL; 236*0Sstevel@tonic-gate if(isset) sktag = V_ASN1_SET; 237*0Sstevel@tonic-gate else sktag = V_ASN1_SEQUENCE; 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate /* Now work out length of items */ 240*0Sstevel@tonic-gate skcontlen = 0; 241*0Sstevel@tonic-gate for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) { 242*0Sstevel@tonic-gate skitem = sk_ASN1_VALUE_value(sk, i); 243*0Sstevel@tonic-gate skcontlen += ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0); 244*0Sstevel@tonic-gate } 245*0Sstevel@tonic-gate sklen = ASN1_object_size(1, skcontlen, sktag); 246*0Sstevel@tonic-gate /* If EXPLICIT need length of surrounding tag */ 247*0Sstevel@tonic-gate if(flags & ASN1_TFLG_EXPTAG) 248*0Sstevel@tonic-gate ret = ASN1_object_size(1, sklen, tt->tag); 249*0Sstevel@tonic-gate else ret = sklen; 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate if(!out) return ret; 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate /* Now encode this lot... */ 254*0Sstevel@tonic-gate /* EXPLICIT tag */ 255*0Sstevel@tonic-gate if(flags & ASN1_TFLG_EXPTAG) 256*0Sstevel@tonic-gate ASN1_put_object(out, 1, sklen, tt->tag, aclass); 257*0Sstevel@tonic-gate /* SET or SEQUENCE and IMPLICIT tag */ 258*0Sstevel@tonic-gate ASN1_put_object(out, 1, skcontlen, sktag, skaclass); 259*0Sstevel@tonic-gate /* And finally the stuff itself */ 260*0Sstevel@tonic-gate asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset); 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate return ret; 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate if(flags & ASN1_TFLG_EXPTAG) { 266*0Sstevel@tonic-gate /* EXPLICIT tagging */ 267*0Sstevel@tonic-gate /* Find length of tagged item */ 268*0Sstevel@tonic-gate i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0); 269*0Sstevel@tonic-gate if(!i) return 0; 270*0Sstevel@tonic-gate /* Find length of EXPLICIT tag */ 271*0Sstevel@tonic-gate ret = ASN1_object_size(1, i, tt->tag); 272*0Sstevel@tonic-gate if(out) { 273*0Sstevel@tonic-gate /* Output tag and item */ 274*0Sstevel@tonic-gate ASN1_put_object(out, 1, i, tt->tag, aclass); 275*0Sstevel@tonic-gate ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate return ret; 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate if(flags & ASN1_TFLG_IMPTAG) { 280*0Sstevel@tonic-gate /* IMPLICIT tagging */ 281*0Sstevel@tonic-gate return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), tt->tag, aclass); 282*0Sstevel@tonic-gate } 283*0Sstevel@tonic-gate /* Nothing special: treat as normal */ 284*0Sstevel@tonic-gate return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0); 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate /* Temporary structure used to hold DER encoding of items for SET OF */ 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate typedef struct { 290*0Sstevel@tonic-gate unsigned char *data; 291*0Sstevel@tonic-gate int length; 292*0Sstevel@tonic-gate ASN1_VALUE *field; 293*0Sstevel@tonic-gate } DER_ENC; 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate static int der_cmp(const void *a, const void *b) 296*0Sstevel@tonic-gate { 297*0Sstevel@tonic-gate const DER_ENC *d1 = a, *d2 = b; 298*0Sstevel@tonic-gate int cmplen, i; 299*0Sstevel@tonic-gate cmplen = (d1->length < d2->length) ? d1->length : d2->length; 300*0Sstevel@tonic-gate i = memcmp(d1->data, d2->data, cmplen); 301*0Sstevel@tonic-gate if(i) return i; 302*0Sstevel@tonic-gate return d1->length - d2->length; 303*0Sstevel@tonic-gate } 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate /* Output the content octets of SET OF or SEQUENCE OF */ 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int do_sort) 308*0Sstevel@tonic-gate { 309*0Sstevel@tonic-gate int i; 310*0Sstevel@tonic-gate ASN1_VALUE *skitem; 311*0Sstevel@tonic-gate unsigned char *tmpdat = NULL, *p = NULL; 312*0Sstevel@tonic-gate DER_ENC *derlst = NULL, *tder; 313*0Sstevel@tonic-gate if(do_sort) { 314*0Sstevel@tonic-gate /* Don't need to sort less than 2 items */ 315*0Sstevel@tonic-gate if(sk_ASN1_VALUE_num(sk) < 2) do_sort = 0; 316*0Sstevel@tonic-gate else { 317*0Sstevel@tonic-gate derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) * sizeof(*derlst)); 318*0Sstevel@tonic-gate tmpdat = OPENSSL_malloc(skcontlen); 319*0Sstevel@tonic-gate if(!derlst || !tmpdat) return 0; 320*0Sstevel@tonic-gate } 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate /* If not sorting just output each item */ 323*0Sstevel@tonic-gate if(!do_sort) { 324*0Sstevel@tonic-gate for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) { 325*0Sstevel@tonic-gate skitem = sk_ASN1_VALUE_value(sk, i); 326*0Sstevel@tonic-gate ASN1_item_i2d(skitem, out, item); 327*0Sstevel@tonic-gate } 328*0Sstevel@tonic-gate return 1; 329*0Sstevel@tonic-gate } 330*0Sstevel@tonic-gate p = tmpdat; 331*0Sstevel@tonic-gate /* Doing sort: build up a list of each member's DER encoding */ 332*0Sstevel@tonic-gate for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { 333*0Sstevel@tonic-gate skitem = sk_ASN1_VALUE_value(sk, i); 334*0Sstevel@tonic-gate tder->data = p; 335*0Sstevel@tonic-gate tder->length = ASN1_item_i2d(skitem, &p, item); 336*0Sstevel@tonic-gate tder->field = skitem; 337*0Sstevel@tonic-gate } 338*0Sstevel@tonic-gate /* Now sort them */ 339*0Sstevel@tonic-gate qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); 340*0Sstevel@tonic-gate /* Output sorted DER encoding */ 341*0Sstevel@tonic-gate p = *out; 342*0Sstevel@tonic-gate for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { 343*0Sstevel@tonic-gate memcpy(p, tder->data, tder->length); 344*0Sstevel@tonic-gate p += tder->length; 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate *out = p; 347*0Sstevel@tonic-gate /* If do_sort is 2 then reorder the STACK */ 348*0Sstevel@tonic-gate if(do_sort == 2) { 349*0Sstevel@tonic-gate for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) 350*0Sstevel@tonic-gate sk_ASN1_VALUE_set(sk, i, tder->field); 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate OPENSSL_free(derlst); 353*0Sstevel@tonic-gate OPENSSL_free(tmpdat); 354*0Sstevel@tonic-gate return 1; 355*0Sstevel@tonic-gate } 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) 358*0Sstevel@tonic-gate { 359*0Sstevel@tonic-gate int len; 360*0Sstevel@tonic-gate int utype; 361*0Sstevel@tonic-gate int usetag; 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate utype = it->utype; 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate /* Get length of content octets and maybe find 366*0Sstevel@tonic-gate * out the underlying type. 367*0Sstevel@tonic-gate */ 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate len = asn1_ex_i2c(pval, NULL, &utype, it); 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate /* If SEQUENCE, SET or OTHER then header is 372*0Sstevel@tonic-gate * included in pseudo content octets so don't 373*0Sstevel@tonic-gate * include tag+length. We need to check here 374*0Sstevel@tonic-gate * because the call to asn1_ex_i2c() could change 375*0Sstevel@tonic-gate * utype. 376*0Sstevel@tonic-gate */ 377*0Sstevel@tonic-gate if((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || 378*0Sstevel@tonic-gate (utype == V_ASN1_OTHER)) 379*0Sstevel@tonic-gate usetag = 0; 380*0Sstevel@tonic-gate else usetag = 1; 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate /* -1 means omit type */ 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate if(len == -1) return 0; 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate /* If not implicitly tagged get tag from underlying type */ 387*0Sstevel@tonic-gate if(tag == -1) tag = utype; 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gate /* Output tag+length followed by content octets */ 390*0Sstevel@tonic-gate if(out) { 391*0Sstevel@tonic-gate if(usetag) ASN1_put_object(out, 0, len, tag, aclass); 392*0Sstevel@tonic-gate asn1_ex_i2c(pval, *out, &utype, it); 393*0Sstevel@tonic-gate *out += len; 394*0Sstevel@tonic-gate } 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate if(usetag) return ASN1_object_size(0, len, tag); 397*0Sstevel@tonic-gate return len; 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate /* Produce content octets from a structure */ 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, const ASN1_ITEM *it) 403*0Sstevel@tonic-gate { 404*0Sstevel@tonic-gate ASN1_BOOLEAN *tbool = NULL; 405*0Sstevel@tonic-gate ASN1_STRING *strtmp; 406*0Sstevel@tonic-gate ASN1_OBJECT *otmp; 407*0Sstevel@tonic-gate int utype; 408*0Sstevel@tonic-gate unsigned char *cont, c; 409*0Sstevel@tonic-gate int len; 410*0Sstevel@tonic-gate const ASN1_PRIMITIVE_FUNCS *pf; 411*0Sstevel@tonic-gate pf = it->funcs; 412*0Sstevel@tonic-gate if(pf && pf->prim_i2c) return pf->prim_i2c(pval, cout, putype, it); 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate /* Should type be omitted? */ 415*0Sstevel@tonic-gate if((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) { 416*0Sstevel@tonic-gate if(!*pval) return -1; 417*0Sstevel@tonic-gate } 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate if(it->itype == ASN1_ITYPE_MSTRING) { 420*0Sstevel@tonic-gate /* If MSTRING type set the underlying type */ 421*0Sstevel@tonic-gate strtmp = (ASN1_STRING *)*pval; 422*0Sstevel@tonic-gate utype = strtmp->type; 423*0Sstevel@tonic-gate *putype = utype; 424*0Sstevel@tonic-gate } else if(it->utype == V_ASN1_ANY) { 425*0Sstevel@tonic-gate /* If ANY set type and pointer to value */ 426*0Sstevel@tonic-gate ASN1_TYPE *typ; 427*0Sstevel@tonic-gate typ = (ASN1_TYPE *)*pval; 428*0Sstevel@tonic-gate utype = typ->type; 429*0Sstevel@tonic-gate *putype = utype; 430*0Sstevel@tonic-gate pval = (ASN1_VALUE **)&typ->value.ptr; 431*0Sstevel@tonic-gate } else utype = *putype; 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate switch(utype) { 434*0Sstevel@tonic-gate case V_ASN1_OBJECT: 435*0Sstevel@tonic-gate otmp = (ASN1_OBJECT *)*pval; 436*0Sstevel@tonic-gate cont = otmp->data; 437*0Sstevel@tonic-gate len = otmp->length; 438*0Sstevel@tonic-gate break; 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate case V_ASN1_NULL: 441*0Sstevel@tonic-gate cont = NULL; 442*0Sstevel@tonic-gate len = 0; 443*0Sstevel@tonic-gate break; 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate case V_ASN1_BOOLEAN: 446*0Sstevel@tonic-gate tbool = (ASN1_BOOLEAN *)pval; 447*0Sstevel@tonic-gate if(*tbool == -1) return -1; 448*0Sstevel@tonic-gate /* Default handling if value == size field then omit */ 449*0Sstevel@tonic-gate if(*tbool && (it->size > 0)) return -1; 450*0Sstevel@tonic-gate if(!*tbool && !it->size) return -1; 451*0Sstevel@tonic-gate c = (unsigned char)*tbool; 452*0Sstevel@tonic-gate cont = &c; 453*0Sstevel@tonic-gate len = 1; 454*0Sstevel@tonic-gate break; 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate case V_ASN1_BIT_STRING: 457*0Sstevel@tonic-gate return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL); 458*0Sstevel@tonic-gate break; 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate case V_ASN1_INTEGER: 461*0Sstevel@tonic-gate case V_ASN1_NEG_INTEGER: 462*0Sstevel@tonic-gate case V_ASN1_ENUMERATED: 463*0Sstevel@tonic-gate case V_ASN1_NEG_ENUMERATED: 464*0Sstevel@tonic-gate /* These are all have the same content format 465*0Sstevel@tonic-gate * as ASN1_INTEGER 466*0Sstevel@tonic-gate */ 467*0Sstevel@tonic-gate return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); 468*0Sstevel@tonic-gate break; 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate case V_ASN1_OCTET_STRING: 471*0Sstevel@tonic-gate case V_ASN1_NUMERICSTRING: 472*0Sstevel@tonic-gate case V_ASN1_PRINTABLESTRING: 473*0Sstevel@tonic-gate case V_ASN1_T61STRING: 474*0Sstevel@tonic-gate case V_ASN1_VIDEOTEXSTRING: 475*0Sstevel@tonic-gate case V_ASN1_IA5STRING: 476*0Sstevel@tonic-gate case V_ASN1_UTCTIME: 477*0Sstevel@tonic-gate case V_ASN1_GENERALIZEDTIME: 478*0Sstevel@tonic-gate case V_ASN1_GRAPHICSTRING: 479*0Sstevel@tonic-gate case V_ASN1_VISIBLESTRING: 480*0Sstevel@tonic-gate case V_ASN1_GENERALSTRING: 481*0Sstevel@tonic-gate case V_ASN1_UNIVERSALSTRING: 482*0Sstevel@tonic-gate case V_ASN1_BMPSTRING: 483*0Sstevel@tonic-gate case V_ASN1_UTF8STRING: 484*0Sstevel@tonic-gate case V_ASN1_SEQUENCE: 485*0Sstevel@tonic-gate case V_ASN1_SET: 486*0Sstevel@tonic-gate default: 487*0Sstevel@tonic-gate /* All based on ASN1_STRING and handled the same */ 488*0Sstevel@tonic-gate strtmp = (ASN1_STRING *)*pval; 489*0Sstevel@tonic-gate cont = strtmp->data; 490*0Sstevel@tonic-gate len = strtmp->length; 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate break; 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate } 495*0Sstevel@tonic-gate if(cout && len) memcpy(cout, cont, len); 496*0Sstevel@tonic-gate return len; 497*0Sstevel@tonic-gate } 498