xref: /plan9/sys/src/cmd/unix/drawterm/libsec/x509.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include <mp.h>
4*8ccd4a63SDavid du Colombier #include <libsec.h>
5*8ccd4a63SDavid du Colombier 
6*8ccd4a63SDavid du Colombier typedef DigestState*(*DigestFun)(uchar*,ulong,uchar*,DigestState*);
7*8ccd4a63SDavid du Colombier 
8*8ccd4a63SDavid du Colombier /* ANSI offsetof, backwards. */
9*8ccd4a63SDavid du Colombier #define	OFFSETOF(a, b)	offsetof(b, a)
10*8ccd4a63SDavid du Colombier 
11*8ccd4a63SDavid du Colombier /*=============================================================*/
12*8ccd4a63SDavid du Colombier /*  general ASN1 declarations and parsing
13*8ccd4a63SDavid du Colombier  *
14*8ccd4a63SDavid du Colombier  *  For now, this is used only for extracting the key from an
15*8ccd4a63SDavid du Colombier  *  X509 certificate, so the entire collection is hidden.  But
16*8ccd4a63SDavid du Colombier  *  someday we should probably make the functions visible and
17*8ccd4a63SDavid du Colombier  *  give them their own man page.
18*8ccd4a63SDavid du Colombier  */
19*8ccd4a63SDavid du Colombier typedef struct Elem Elem;
20*8ccd4a63SDavid du Colombier typedef struct Tag Tag;
21*8ccd4a63SDavid du Colombier typedef struct Value Value;
22*8ccd4a63SDavid du Colombier typedef struct Bytes Bytes;
23*8ccd4a63SDavid du Colombier typedef struct Ints Ints;
24*8ccd4a63SDavid du Colombier typedef struct Bits Bits;
25*8ccd4a63SDavid du Colombier typedef struct Elist Elist;
26*8ccd4a63SDavid du Colombier 
27*8ccd4a63SDavid du Colombier /* tag classes */
28*8ccd4a63SDavid du Colombier #define Universal 0
29*8ccd4a63SDavid du Colombier #define Context 0x80
30*8ccd4a63SDavid du Colombier 
31*8ccd4a63SDavid du Colombier /* universal tags */
32*8ccd4a63SDavid du Colombier #define BOOLEAN 1
33*8ccd4a63SDavid du Colombier #define INTEGER 2
34*8ccd4a63SDavid du Colombier #define BIT_STRING 3
35*8ccd4a63SDavid du Colombier #define OCTET_STRING 4
36*8ccd4a63SDavid du Colombier #define NULLTAG 5
37*8ccd4a63SDavid du Colombier #define OBJECT_ID 6
38*8ccd4a63SDavid du Colombier #define ObjectDescriptor 7
39*8ccd4a63SDavid du Colombier #define EXTERNAL 8
40*8ccd4a63SDavid du Colombier #define REAL 9
41*8ccd4a63SDavid du Colombier #define ENUMERATED 10
42*8ccd4a63SDavid du Colombier #define EMBEDDED_PDV 11
43*8ccd4a63SDavid du Colombier #define SEQUENCE 16		/* also SEQUENCE OF */
44*8ccd4a63SDavid du Colombier #define SETOF 17				/* also SETOF OF */
45*8ccd4a63SDavid du Colombier #define NumericString 18
46*8ccd4a63SDavid du Colombier #define PrintableString 19
47*8ccd4a63SDavid du Colombier #define TeletexString 20
48*8ccd4a63SDavid du Colombier #define VideotexString 21
49*8ccd4a63SDavid du Colombier #define IA5String 22
50*8ccd4a63SDavid du Colombier #define UTCTime 23
51*8ccd4a63SDavid du Colombier #define GeneralizedTime 24
52*8ccd4a63SDavid du Colombier #define GraphicString 25
53*8ccd4a63SDavid du Colombier #define VisibleString 26
54*8ccd4a63SDavid du Colombier #define GeneralString 27
55*8ccd4a63SDavid du Colombier #define UniversalString 28
56*8ccd4a63SDavid du Colombier #define BMPString 30
57*8ccd4a63SDavid du Colombier 
58*8ccd4a63SDavid du Colombier struct Bytes {
59*8ccd4a63SDavid du Colombier 	int	len;
60*8ccd4a63SDavid du Colombier 	uchar	data[1];
61*8ccd4a63SDavid du Colombier };
62*8ccd4a63SDavid du Colombier 
63*8ccd4a63SDavid du Colombier struct Ints {
64*8ccd4a63SDavid du Colombier 	int	len;
65*8ccd4a63SDavid du Colombier 	int	data[1];
66*8ccd4a63SDavid du Colombier };
67*8ccd4a63SDavid du Colombier 
68*8ccd4a63SDavid du Colombier struct Bits {
69*8ccd4a63SDavid du Colombier 	int	len;		/* number of bytes */
70*8ccd4a63SDavid du Colombier 	int	unusedbits;	/* unused bits in last byte */
71*8ccd4a63SDavid du Colombier 	uchar	data[1];	/* most-significant bit first */
72*8ccd4a63SDavid du Colombier };
73*8ccd4a63SDavid du Colombier 
74*8ccd4a63SDavid du Colombier struct Tag {
75*8ccd4a63SDavid du Colombier 	int	class;
76*8ccd4a63SDavid du Colombier 	int	num;
77*8ccd4a63SDavid du Colombier };
78*8ccd4a63SDavid du Colombier 
79*8ccd4a63SDavid du Colombier enum { VBool, VInt, VOctets, VBigInt, VReal, VOther,
80*8ccd4a63SDavid du Colombier 	VBitString, VNull, VEOC, VObjId, VString, VSeq, VSet };
81*8ccd4a63SDavid du Colombier struct Value {
82*8ccd4a63SDavid du Colombier 	int	tag;		/* VBool, etc. */
83*8ccd4a63SDavid du Colombier 	union {
84*8ccd4a63SDavid du Colombier 		int	boolval;
85*8ccd4a63SDavid du Colombier 		int	intval;
86*8ccd4a63SDavid du Colombier 		Bytes*	octetsval;
87*8ccd4a63SDavid du Colombier 		Bytes*	bigintval;
88*8ccd4a63SDavid du Colombier 		Bytes*	realval;	/* undecoded; hardly ever used */
89*8ccd4a63SDavid du Colombier 		Bytes*	otherval;
90*8ccd4a63SDavid du Colombier 		Bits*	bitstringval;
91*8ccd4a63SDavid du Colombier 		Ints*	objidval;
92*8ccd4a63SDavid du Colombier 		char*	stringval;
93*8ccd4a63SDavid du Colombier 		Elist*	seqval;
94*8ccd4a63SDavid du Colombier 		Elist*	setval;
95*8ccd4a63SDavid du Colombier 	} u;  /* (Don't use anonymous unions, for ease of porting) */
96*8ccd4a63SDavid du Colombier };
97*8ccd4a63SDavid du Colombier 
98*8ccd4a63SDavid du Colombier struct Elem {
99*8ccd4a63SDavid du Colombier 	Tag	tag;
100*8ccd4a63SDavid du Colombier 	Value	val;
101*8ccd4a63SDavid du Colombier };
102*8ccd4a63SDavid du Colombier 
103*8ccd4a63SDavid du Colombier struct Elist {
104*8ccd4a63SDavid du Colombier 	Elist*	tl;
105*8ccd4a63SDavid du Colombier 	Elem	hd;
106*8ccd4a63SDavid du Colombier };
107*8ccd4a63SDavid du Colombier 
108*8ccd4a63SDavid du Colombier /* decoding errors */
109*8ccd4a63SDavid du Colombier enum { ASN_OK, ASN_ESHORT, ASN_ETOOBIG, ASN_EVALLEN,
110*8ccd4a63SDavid du Colombier 		ASN_ECONSTR, ASN_EPRIM, ASN_EINVAL, ASN_EUNIMPL };
111*8ccd4a63SDavid du Colombier 
112*8ccd4a63SDavid du Colombier 
113*8ccd4a63SDavid du Colombier /* here are the functions to consider making extern someday */
114*8ccd4a63SDavid du Colombier static Bytes*	newbytes(int len);
115*8ccd4a63SDavid du Colombier static Bytes*	makebytes(uchar* buf, int len);
116*8ccd4a63SDavid du Colombier static void	freebytes(Bytes* b);
117*8ccd4a63SDavid du Colombier static Bytes*	catbytes(Bytes* b1, Bytes* b2);
118*8ccd4a63SDavid du Colombier static Ints*	newints(int len);
119*8ccd4a63SDavid du Colombier static Ints*	makeints(int* buf, int len);
120*8ccd4a63SDavid du Colombier static void	freeints(Ints* b);
121*8ccd4a63SDavid du Colombier static Bits*	newbits(int len);
122*8ccd4a63SDavid du Colombier static Bits*	makebits(uchar* buf, int len, int unusedbits);
123*8ccd4a63SDavid du Colombier static void	freebits(Bits* b);
124*8ccd4a63SDavid du Colombier static Elist*	mkel(Elem e, Elist* tail);
125*8ccd4a63SDavid du Colombier static void	freeelist(Elist* el);
126*8ccd4a63SDavid du Colombier static int	elistlen(Elist* el);
127*8ccd4a63SDavid du Colombier static int	is_seq(Elem* pe, Elist** pseq);
128*8ccd4a63SDavid du Colombier static int	is_set(Elem* pe, Elist** pset);
129*8ccd4a63SDavid du Colombier static int	is_int(Elem* pe, int* pint);
130*8ccd4a63SDavid du Colombier static int	is_bigint(Elem* pe, Bytes** pbigint);
131*8ccd4a63SDavid du Colombier static int	is_bitstring(Elem* pe, Bits** pbits);
132*8ccd4a63SDavid du Colombier static int	is_octetstring(Elem* pe, Bytes** poctets);
133*8ccd4a63SDavid du Colombier static int	is_oid(Elem* pe, Ints** poid);
134*8ccd4a63SDavid du Colombier static int	is_string(Elem* pe, char** pstring);
135*8ccd4a63SDavid du Colombier static int	is_time(Elem* pe, char** ptime);
136*8ccd4a63SDavid du Colombier static int	decode(uchar* a, int alen, Elem* pelem);
137*8ccd4a63SDavid du Colombier static int	decode_seq(uchar* a, int alen, Elist** pelist);
138*8ccd4a63SDavid du Colombier static int	decode_value(uchar* a, int alen, int kind, int isconstr, Value* pval);
139*8ccd4a63SDavid du Colombier static int	encode(Elem e, Bytes** pbytes);
140*8ccd4a63SDavid du Colombier static int	oid_lookup(Ints* o, Ints** tab);
141*8ccd4a63SDavid du Colombier static void	freevalfields(Value* v);
142*8ccd4a63SDavid du Colombier static mpint	*asn1mpint(Elem *e);
143*8ccd4a63SDavid du Colombier 
144*8ccd4a63SDavid du Colombier 
145*8ccd4a63SDavid du Colombier 
146*8ccd4a63SDavid du Colombier #define TAG_MASK 0x1F
147*8ccd4a63SDavid du Colombier #define CONSTR_MASK 0x20
148*8ccd4a63SDavid du Colombier #define CLASS_MASK 0xC0
149*8ccd4a63SDavid du Colombier #define MAXOBJIDLEN 20
150*8ccd4a63SDavid du Colombier 
151*8ccd4a63SDavid du Colombier static int ber_decode(uchar** pp, uchar* pend, Elem* pelem);
152*8ccd4a63SDavid du Colombier static int tag_decode(uchar** pp, uchar* pend, Tag* ptag, int* pisconstr);
153*8ccd4a63SDavid du Colombier static int length_decode(uchar** pp, uchar* pend, int* plength);
154*8ccd4a63SDavid du Colombier static int value_decode(uchar** pp, uchar* pend, int length, int kind, int isconstr, Value* pval);
155*8ccd4a63SDavid du Colombier static int int_decode(uchar** pp, uchar* pend, int count, int unsgned, int* pint);
156*8ccd4a63SDavid du Colombier static int uint7_decode(uchar** pp, uchar* pend, int* pint);
157*8ccd4a63SDavid du Colombier static int octet_decode(uchar** pp, uchar* pend, int length, int isconstr, Bytes** pbytes);
158*8ccd4a63SDavid du Colombier static int seq_decode(uchar** pp, uchar* pend, int length, int isconstr, Elist** pelist);
159*8ccd4a63SDavid du Colombier static int enc(uchar** pp, Elem e, int lenonly);
160*8ccd4a63SDavid du Colombier static int val_enc(uchar** pp, Elem e, int *pconstr, int lenonly);
161*8ccd4a63SDavid du Colombier static void uint7_enc(uchar** pp, int num, int lenonly);
162*8ccd4a63SDavid du Colombier static void int_enc(uchar** pp, int num, int unsgned, int lenonly);
163*8ccd4a63SDavid du Colombier 
164*8ccd4a63SDavid du Colombier static void *
emalloc(int n)165*8ccd4a63SDavid du Colombier emalloc(int n)
166*8ccd4a63SDavid du Colombier {
167*8ccd4a63SDavid du Colombier 	void *p;
168*8ccd4a63SDavid du Colombier 	if(n==0)
169*8ccd4a63SDavid du Colombier 		n=1;
170*8ccd4a63SDavid du Colombier 	p = malloc(n);
171*8ccd4a63SDavid du Colombier 	if(p == nil){
172*8ccd4a63SDavid du Colombier 		exits("out of memory");
173*8ccd4a63SDavid du Colombier 	}
174*8ccd4a63SDavid du Colombier 	memset(p, 0, n);
175*8ccd4a63SDavid du Colombier 	return p;
176*8ccd4a63SDavid du Colombier }
177*8ccd4a63SDavid du Colombier 
178*8ccd4a63SDavid du Colombier static char*
estrdup(char * s)179*8ccd4a63SDavid du Colombier estrdup(char *s)
180*8ccd4a63SDavid du Colombier {
181*8ccd4a63SDavid du Colombier 	char *d, *d0;
182*8ccd4a63SDavid du Colombier 
183*8ccd4a63SDavid du Colombier 	if(!s)
184*8ccd4a63SDavid du Colombier 		return 0;
185*8ccd4a63SDavid du Colombier 	d = d0 = emalloc(strlen(s)+1);
186*8ccd4a63SDavid du Colombier 	while(*d++ = *s++)
187*8ccd4a63SDavid du Colombier 		;
188*8ccd4a63SDavid du Colombier 	return d0;
189*8ccd4a63SDavid du Colombier }
190*8ccd4a63SDavid du Colombier 
191*8ccd4a63SDavid du Colombier 
192*8ccd4a63SDavid du Colombier /*
193*8ccd4a63SDavid du Colombier  * Decode a[0..len] as a BER encoding of an ASN1 type.
194*8ccd4a63SDavid du Colombier  * The return value is one of ASN_OK, etc.
195*8ccd4a63SDavid du Colombier  * Depending on the error, the returned elem may or may not
196*8ccd4a63SDavid du Colombier  * be nil.
197*8ccd4a63SDavid du Colombier  */
198*8ccd4a63SDavid du Colombier static int
decode(uchar * a,int alen,Elem * pelem)199*8ccd4a63SDavid du Colombier decode(uchar* a, int alen, Elem* pelem)
200*8ccd4a63SDavid du Colombier {
201*8ccd4a63SDavid du Colombier 	uchar* p = a;
202*8ccd4a63SDavid du Colombier 
203*8ccd4a63SDavid du Colombier 	return  ber_decode(&p, &a[alen], pelem);
204*8ccd4a63SDavid du Colombier }
205*8ccd4a63SDavid du Colombier 
206*8ccd4a63SDavid du Colombier /*
207*8ccd4a63SDavid du Colombier  * Like decode, but continue decoding after first element
208*8ccd4a63SDavid du Colombier  * of array ends.
209*8ccd4a63SDavid du Colombier  */
210*8ccd4a63SDavid du Colombier static int
decode_seq(uchar * a,int alen,Elist ** pelist)211*8ccd4a63SDavid du Colombier decode_seq(uchar* a, int alen, Elist** pelist)
212*8ccd4a63SDavid du Colombier {
213*8ccd4a63SDavid du Colombier 	uchar* p = a;
214*8ccd4a63SDavid du Colombier 
215*8ccd4a63SDavid du Colombier 	return seq_decode(&p, &a[alen], -1, 1, pelist);
216*8ccd4a63SDavid du Colombier }
217*8ccd4a63SDavid du Colombier 
218*8ccd4a63SDavid du Colombier /*
219*8ccd4a63SDavid du Colombier  * Decode the whole array as a BER encoding of an ASN1 value,
220*8ccd4a63SDavid du Colombier  * (i.e., the part after the tag and length).
221*8ccd4a63SDavid du Colombier  * Assume the value is encoded as universal tag "kind".
222*8ccd4a63SDavid du Colombier  * The constr arg is 1 if the value is constructed, 0 if primitive.
223*8ccd4a63SDavid du Colombier  * If there's an error, the return string will contain the error.
224*8ccd4a63SDavid du Colombier  * Depending on the error, the returned value may or may not
225*8ccd4a63SDavid du Colombier  * be nil.
226*8ccd4a63SDavid du Colombier  */
227*8ccd4a63SDavid du Colombier static int
decode_value(uchar * a,int alen,int kind,int isconstr,Value * pval)228*8ccd4a63SDavid du Colombier decode_value(uchar* a, int alen, int kind, int isconstr, Value* pval)
229*8ccd4a63SDavid du Colombier {
230*8ccd4a63SDavid du Colombier 	uchar* p = a;
231*8ccd4a63SDavid du Colombier 
232*8ccd4a63SDavid du Colombier 	return value_decode(&p, &a[alen], alen, kind, isconstr, pval);
233*8ccd4a63SDavid du Colombier }
234*8ccd4a63SDavid du Colombier 
235*8ccd4a63SDavid du Colombier /*
236*8ccd4a63SDavid du Colombier  * All of the following decoding routines take arguments:
237*8ccd4a63SDavid du Colombier  *	uchar **pp;
238*8ccd4a63SDavid du Colombier  *	uchar *pend;
239*8ccd4a63SDavid du Colombier  * Where parsing is supposed to start at **pp, and when parsing
240*8ccd4a63SDavid du Colombier  * is done, *pp is updated to point at next char to be parsed.
241*8ccd4a63SDavid du Colombier  * The pend pointer is just past end of string; an error should
242*8ccd4a63SDavid du Colombier  * be returned parsing hasn't finished by then.
243*8ccd4a63SDavid du Colombier  *
244*8ccd4a63SDavid du Colombier  * The returned int is ASN_OK if all went fine, else ASN_ESHORT, etc.
245*8ccd4a63SDavid du Colombier  * The remaining argument(s) are pointers to where parsed entity goes.
246*8ccd4a63SDavid du Colombier  */
247*8ccd4a63SDavid du Colombier 
248*8ccd4a63SDavid du Colombier /* Decode an ASN1 'Elem' (tag, length, value) */
249*8ccd4a63SDavid du Colombier static int
ber_decode(uchar ** pp,uchar * pend,Elem * pelem)250*8ccd4a63SDavid du Colombier ber_decode(uchar** pp, uchar* pend, Elem* pelem)
251*8ccd4a63SDavid du Colombier {
252*8ccd4a63SDavid du Colombier 	int err;
253*8ccd4a63SDavid du Colombier 	int isconstr;
254*8ccd4a63SDavid du Colombier 	int length;
255*8ccd4a63SDavid du Colombier 	Tag tag;
256*8ccd4a63SDavid du Colombier 	Value val;
257*8ccd4a63SDavid du Colombier 
258*8ccd4a63SDavid du Colombier 	err = tag_decode(pp, pend, &tag, &isconstr);
259*8ccd4a63SDavid du Colombier 	if(err == ASN_OK) {
260*8ccd4a63SDavid du Colombier 		err = length_decode(pp, pend, &length);
261*8ccd4a63SDavid du Colombier 		if(err == ASN_OK) {
262*8ccd4a63SDavid du Colombier 			if(tag.class == Universal)
263*8ccd4a63SDavid du Colombier 				err = value_decode(pp, pend, length, tag.num, isconstr, &val);
264*8ccd4a63SDavid du Colombier 			else
265*8ccd4a63SDavid du Colombier 				err = value_decode(pp, pend, length, OCTET_STRING, 0, &val);
266*8ccd4a63SDavid du Colombier 			if(err == ASN_OK) {
267*8ccd4a63SDavid du Colombier 				pelem->tag = tag;
268*8ccd4a63SDavid du Colombier 				pelem->val = val;
269*8ccd4a63SDavid du Colombier 			}
270*8ccd4a63SDavid du Colombier 		}
271*8ccd4a63SDavid du Colombier 	}
272*8ccd4a63SDavid du Colombier 	return err;
273*8ccd4a63SDavid du Colombier }
274*8ccd4a63SDavid du Colombier 
275*8ccd4a63SDavid du Colombier /* Decode a tag field */
276*8ccd4a63SDavid du Colombier static int
tag_decode(uchar ** pp,uchar * pend,Tag * ptag,int * pisconstr)277*8ccd4a63SDavid du Colombier tag_decode(uchar** pp, uchar* pend, Tag* ptag, int* pisconstr)
278*8ccd4a63SDavid du Colombier {
279*8ccd4a63SDavid du Colombier 	int err;
280*8ccd4a63SDavid du Colombier 	int v;
281*8ccd4a63SDavid du Colombier 	uchar* p;
282*8ccd4a63SDavid du Colombier 
283*8ccd4a63SDavid du Colombier 	err = ASN_OK;
284*8ccd4a63SDavid du Colombier 	p = *pp;
285*8ccd4a63SDavid du Colombier 	if(pend-p >= 2) {
286*8ccd4a63SDavid du Colombier 		v = *p++;
287*8ccd4a63SDavid du Colombier 		ptag->class = v&CLASS_MASK;
288*8ccd4a63SDavid du Colombier 		if(v&CONSTR_MASK)
289*8ccd4a63SDavid du Colombier 			*pisconstr = 1;
290*8ccd4a63SDavid du Colombier 		else
291*8ccd4a63SDavid du Colombier 			*pisconstr = 0;
292*8ccd4a63SDavid du Colombier 		v &= TAG_MASK;
293*8ccd4a63SDavid du Colombier 		if(v == TAG_MASK)
294*8ccd4a63SDavid du Colombier 			err = uint7_decode(&p, pend, &v);
295*8ccd4a63SDavid du Colombier 		ptag->num = v;
296*8ccd4a63SDavid du Colombier 	}
297*8ccd4a63SDavid du Colombier 	else
298*8ccd4a63SDavid du Colombier 		err = ASN_ESHORT;
299*8ccd4a63SDavid du Colombier 	*pp = p;
300*8ccd4a63SDavid du Colombier 	return err;
301*8ccd4a63SDavid du Colombier }
302*8ccd4a63SDavid du Colombier 
303*8ccd4a63SDavid du Colombier /* Decode a length field */
304*8ccd4a63SDavid du Colombier static int
length_decode(uchar ** pp,uchar * pend,int * plength)305*8ccd4a63SDavid du Colombier length_decode(uchar** pp, uchar* pend, int* plength)
306*8ccd4a63SDavid du Colombier {
307*8ccd4a63SDavid du Colombier 	int err;
308*8ccd4a63SDavid du Colombier 	int num;
309*8ccd4a63SDavid du Colombier 	int v;
310*8ccd4a63SDavid du Colombier 	uchar* p;
311*8ccd4a63SDavid du Colombier 
312*8ccd4a63SDavid du Colombier 	err = ASN_OK;
313*8ccd4a63SDavid du Colombier 	num = 0;
314*8ccd4a63SDavid du Colombier 	p = *pp;
315*8ccd4a63SDavid du Colombier 	if(p < pend) {
316*8ccd4a63SDavid du Colombier 		v = *p++;
317*8ccd4a63SDavid du Colombier 		if(v&0x80)
318*8ccd4a63SDavid du Colombier 			err = int_decode(&p, pend, v&0x7F, 1, &num);
319*8ccd4a63SDavid du Colombier 		else if(v == 0x80)
320*8ccd4a63SDavid du Colombier 			num = -1;
321*8ccd4a63SDavid du Colombier 		else
322*8ccd4a63SDavid du Colombier 			num = v;
323*8ccd4a63SDavid du Colombier 	}
324*8ccd4a63SDavid du Colombier 	else
325*8ccd4a63SDavid du Colombier 		err = ASN_ESHORT;
326*8ccd4a63SDavid du Colombier 	*pp = p;
327*8ccd4a63SDavid du Colombier 	*plength = num;
328*8ccd4a63SDavid du Colombier 	return err;
329*8ccd4a63SDavid du Colombier }
330*8ccd4a63SDavid du Colombier 
331*8ccd4a63SDavid du Colombier /* Decode a value field  */
332*8ccd4a63SDavid du Colombier static int
value_decode(uchar ** pp,uchar * pend,int length,int kind,int isconstr,Value * pval)333*8ccd4a63SDavid du Colombier value_decode(uchar** pp, uchar* pend, int length, int kind, int isconstr, Value* pval)
334*8ccd4a63SDavid du Colombier {
335*8ccd4a63SDavid du Colombier 	int err;
336*8ccd4a63SDavid du Colombier 	Bytes* va;
337*8ccd4a63SDavid du Colombier 	int num;
338*8ccd4a63SDavid du Colombier 	int bitsunused;
339*8ccd4a63SDavid du Colombier 	int subids[MAXOBJIDLEN];
340*8ccd4a63SDavid du Colombier 	int isubid;
341*8ccd4a63SDavid du Colombier 	Elist*	vl;
342*8ccd4a63SDavid du Colombier 	uchar* p;
343*8ccd4a63SDavid du Colombier 	uchar* pe;
344*8ccd4a63SDavid du Colombier 
345*8ccd4a63SDavid du Colombier 	err = ASN_OK;
346*8ccd4a63SDavid du Colombier 	p = *pp;
347*8ccd4a63SDavid du Colombier 	if(length == -1) {	/* "indefinite" length spec */
348*8ccd4a63SDavid du Colombier 		if(!isconstr)
349*8ccd4a63SDavid du Colombier 			err = ASN_EINVAL;
350*8ccd4a63SDavid du Colombier 	}
351*8ccd4a63SDavid du Colombier 	else if(p + length > pend)
352*8ccd4a63SDavid du Colombier 		err = ASN_EVALLEN;
353*8ccd4a63SDavid du Colombier 	if(err != ASN_OK)
354*8ccd4a63SDavid du Colombier 		return err;
355*8ccd4a63SDavid du Colombier 
356*8ccd4a63SDavid du Colombier 	switch(kind) {
357*8ccd4a63SDavid du Colombier 	case 0:
358*8ccd4a63SDavid du Colombier 		/* marker for end of indefinite constructions */
359*8ccd4a63SDavid du Colombier 		if(length == 0)
360*8ccd4a63SDavid du Colombier 			pval->tag = VNull;
361*8ccd4a63SDavid du Colombier 		else
362*8ccd4a63SDavid du Colombier 			err = ASN_EINVAL;
363*8ccd4a63SDavid du Colombier 		break;
364*8ccd4a63SDavid du Colombier 
365*8ccd4a63SDavid du Colombier 	case BOOLEAN:
366*8ccd4a63SDavid du Colombier 		if(isconstr)
367*8ccd4a63SDavid du Colombier 			err = ASN_ECONSTR;
368*8ccd4a63SDavid du Colombier 		else if(length != 1)
369*8ccd4a63SDavid du Colombier 			err = ASN_EVALLEN;
370*8ccd4a63SDavid du Colombier 		else {
371*8ccd4a63SDavid du Colombier 			pval->tag = VBool;
372*8ccd4a63SDavid du Colombier 			pval->u.boolval = (*p++ != 0);
373*8ccd4a63SDavid du Colombier 		}
374*8ccd4a63SDavid du Colombier 		break;
375*8ccd4a63SDavid du Colombier 
376*8ccd4a63SDavid du Colombier 	case INTEGER:
377*8ccd4a63SDavid du Colombier 	case ENUMERATED:
378*8ccd4a63SDavid du Colombier 		if(isconstr)
379*8ccd4a63SDavid du Colombier 			err = ASN_ECONSTR;
380*8ccd4a63SDavid du Colombier 		else if(length <= 4) {
381*8ccd4a63SDavid du Colombier 			err = int_decode(&p, pend, length, 0, &num);
382*8ccd4a63SDavid du Colombier 			if(err == ASN_OK) {
383*8ccd4a63SDavid du Colombier 				pval->tag = VInt;
384*8ccd4a63SDavid du Colombier 				pval->u.intval = num;
385*8ccd4a63SDavid du Colombier 			}
386*8ccd4a63SDavid du Colombier 		}
387*8ccd4a63SDavid du Colombier 		else {
388*8ccd4a63SDavid du Colombier 			pval->tag = VBigInt;
389*8ccd4a63SDavid du Colombier 			pval->u.bigintval = makebytes(p, length);
390*8ccd4a63SDavid du Colombier 			p += length;
391*8ccd4a63SDavid du Colombier 		}
392*8ccd4a63SDavid du Colombier 		break;
393*8ccd4a63SDavid du Colombier 
394*8ccd4a63SDavid du Colombier 	case BIT_STRING:
395*8ccd4a63SDavid du Colombier 		pval->tag = VBitString;
396*8ccd4a63SDavid du Colombier 		if(isconstr) {
397*8ccd4a63SDavid du Colombier 			if(length == -1 && p + 2 <= pend && *p == 0 && *(p+1) ==0) {
398*8ccd4a63SDavid du Colombier 				pval->u.bitstringval = makebits(0, 0, 0);
399*8ccd4a63SDavid du Colombier 				p += 2;
400*8ccd4a63SDavid du Colombier 			}
401*8ccd4a63SDavid du Colombier 			else
402*8ccd4a63SDavid du Colombier 				/* TODO: recurse and concat results */
403*8ccd4a63SDavid du Colombier 				err = ASN_EUNIMPL;
404*8ccd4a63SDavid du Colombier 		}
405*8ccd4a63SDavid du Colombier 		else {
406*8ccd4a63SDavid du Colombier 			if(length < 2) {
407*8ccd4a63SDavid du Colombier 				if(length == 1 && *p == 0) {
408*8ccd4a63SDavid du Colombier 					pval->u.bitstringval = makebits(0, 0, 0);
409*8ccd4a63SDavid du Colombier 					p++;
410*8ccd4a63SDavid du Colombier 				}
411*8ccd4a63SDavid du Colombier 				else
412*8ccd4a63SDavid du Colombier 					err = ASN_EINVAL;
413*8ccd4a63SDavid du Colombier 			}
414*8ccd4a63SDavid du Colombier 			else {
415*8ccd4a63SDavid du Colombier 				bitsunused = *p;
416*8ccd4a63SDavid du Colombier 				if(bitsunused > 7)
417*8ccd4a63SDavid du Colombier 					err = ASN_EINVAL;
418*8ccd4a63SDavid du Colombier 				else if(length > 0x0FFFFFFF)
419*8ccd4a63SDavid du Colombier 					err = ASN_ETOOBIG;
420*8ccd4a63SDavid du Colombier 				else {
421*8ccd4a63SDavid du Colombier 					pval->u.bitstringval = makebits(p+1, length-1, bitsunused);
422*8ccd4a63SDavid du Colombier 					p += length;
423*8ccd4a63SDavid du Colombier 				}
424*8ccd4a63SDavid du Colombier 			}
425*8ccd4a63SDavid du Colombier 		}
426*8ccd4a63SDavid du Colombier 		break;
427*8ccd4a63SDavid du Colombier 
428*8ccd4a63SDavid du Colombier 	case OCTET_STRING:
429*8ccd4a63SDavid du Colombier 	case ObjectDescriptor:
430*8ccd4a63SDavid du Colombier 		err = octet_decode(&p, pend, length, isconstr, &va);
431*8ccd4a63SDavid du Colombier 		if(err == ASN_OK) {
432*8ccd4a63SDavid du Colombier 			pval->tag = VOctets;
433*8ccd4a63SDavid du Colombier 			pval->u.octetsval = va;
434*8ccd4a63SDavid du Colombier 		}
435*8ccd4a63SDavid du Colombier 		break;
436*8ccd4a63SDavid du Colombier 
437*8ccd4a63SDavid du Colombier 	case NULLTAG:
438*8ccd4a63SDavid du Colombier 		if(isconstr)
439*8ccd4a63SDavid du Colombier 			err = ASN_ECONSTR;
440*8ccd4a63SDavid du Colombier 		else if(length != 0)
441*8ccd4a63SDavid du Colombier 			err = ASN_EVALLEN;
442*8ccd4a63SDavid du Colombier 		else
443*8ccd4a63SDavid du Colombier 			pval->tag = VNull;
444*8ccd4a63SDavid du Colombier 		break;
445*8ccd4a63SDavid du Colombier 
446*8ccd4a63SDavid du Colombier 	case OBJECT_ID:
447*8ccd4a63SDavid du Colombier 		if(isconstr)
448*8ccd4a63SDavid du Colombier 			err = ASN_ECONSTR;
449*8ccd4a63SDavid du Colombier 		else if(length == 0)
450*8ccd4a63SDavid du Colombier 			err = ASN_EVALLEN;
451*8ccd4a63SDavid du Colombier 		else {
452*8ccd4a63SDavid du Colombier 			isubid = 0;
453*8ccd4a63SDavid du Colombier 			pe = p+length;
454*8ccd4a63SDavid du Colombier 			while(p < pe && isubid < MAXOBJIDLEN) {
455*8ccd4a63SDavid du Colombier 				err = uint7_decode(&p, pend, &num);
456*8ccd4a63SDavid du Colombier 				if(err != ASN_OK)
457*8ccd4a63SDavid du Colombier 					break;
458*8ccd4a63SDavid du Colombier 				if(isubid == 0) {
459*8ccd4a63SDavid du Colombier 					subids[isubid++] = num / 40;
460*8ccd4a63SDavid du Colombier 					subids[isubid++] = num % 40;
461*8ccd4a63SDavid du Colombier 				}
462*8ccd4a63SDavid du Colombier 				else
463*8ccd4a63SDavid du Colombier 					subids[isubid++] = num;
464*8ccd4a63SDavid du Colombier 			}
465*8ccd4a63SDavid du Colombier 			if(err == ASN_OK) {
466*8ccd4a63SDavid du Colombier 				if(p != pe)
467*8ccd4a63SDavid du Colombier 					err = ASN_EVALLEN;
468*8ccd4a63SDavid du Colombier 				else {
469*8ccd4a63SDavid du Colombier 					pval->tag = VObjId;
470*8ccd4a63SDavid du Colombier 					pval->u.objidval = makeints(subids, isubid);
471*8ccd4a63SDavid du Colombier 				}
472*8ccd4a63SDavid du Colombier 			}
473*8ccd4a63SDavid du Colombier 		}
474*8ccd4a63SDavid du Colombier 		break;
475*8ccd4a63SDavid du Colombier 
476*8ccd4a63SDavid du Colombier 	case EXTERNAL:
477*8ccd4a63SDavid du Colombier 	case EMBEDDED_PDV:
478*8ccd4a63SDavid du Colombier 		/* TODO: parse this internally */
479*8ccd4a63SDavid du Colombier 		if(p+length > pend)
480*8ccd4a63SDavid du Colombier 			err = ASN_EVALLEN;
481*8ccd4a63SDavid du Colombier 		else {
482*8ccd4a63SDavid du Colombier 			pval->tag = VOther;
483*8ccd4a63SDavid du Colombier 			pval->u.otherval = makebytes(p, length);
484*8ccd4a63SDavid du Colombier 			p += length;
485*8ccd4a63SDavid du Colombier 		}
486*8ccd4a63SDavid du Colombier 		break;
487*8ccd4a63SDavid du Colombier 
488*8ccd4a63SDavid du Colombier 	case REAL:
489*8ccd4a63SDavid du Colombier 		/* Let the application decode */
490*8ccd4a63SDavid du Colombier 		if(isconstr)
491*8ccd4a63SDavid du Colombier 			err = ASN_ECONSTR;
492*8ccd4a63SDavid du Colombier 		else if(p+length > pend)
493*8ccd4a63SDavid du Colombier 			err = ASN_EVALLEN;
494*8ccd4a63SDavid du Colombier 		else {
495*8ccd4a63SDavid du Colombier 			pval->tag = VReal;
496*8ccd4a63SDavid du Colombier 			pval->u.realval = makebytes(p, length);
497*8ccd4a63SDavid du Colombier 			p += length;
498*8ccd4a63SDavid du Colombier 		}
499*8ccd4a63SDavid du Colombier 		break;
500*8ccd4a63SDavid du Colombier 
501*8ccd4a63SDavid du Colombier 	case SEQUENCE:
502*8ccd4a63SDavid du Colombier 		err = seq_decode(&p, pend, length, isconstr, &vl);
503*8ccd4a63SDavid du Colombier 		if(err == ASN_OK) {
504*8ccd4a63SDavid du Colombier 			pval->tag = VSeq ;
505*8ccd4a63SDavid du Colombier 			pval->u.seqval = vl;
506*8ccd4a63SDavid du Colombier 		}
507*8ccd4a63SDavid du Colombier 		break;
508*8ccd4a63SDavid du Colombier 
509*8ccd4a63SDavid du Colombier 	case SETOF:
510*8ccd4a63SDavid du Colombier 		err = seq_decode(&p, pend, length, isconstr, &vl);
511*8ccd4a63SDavid du Colombier 		if(err == ASN_OK) {
512*8ccd4a63SDavid du Colombier 			pval->tag = VSet;
513*8ccd4a63SDavid du Colombier 			pval->u.setval = vl;
514*8ccd4a63SDavid du Colombier 		}
515*8ccd4a63SDavid du Colombier 		break;
516*8ccd4a63SDavid du Colombier 
517*8ccd4a63SDavid du Colombier 	case NumericString:
518*8ccd4a63SDavid du Colombier 	case PrintableString:
519*8ccd4a63SDavid du Colombier 	case TeletexString:
520*8ccd4a63SDavid du Colombier 	case VideotexString:
521*8ccd4a63SDavid du Colombier 	case IA5String:
522*8ccd4a63SDavid du Colombier 	case UTCTime:
523*8ccd4a63SDavid du Colombier 	case GeneralizedTime:
524*8ccd4a63SDavid du Colombier 	case GraphicString:
525*8ccd4a63SDavid du Colombier 	case VisibleString:
526*8ccd4a63SDavid du Colombier 	case GeneralString:
527*8ccd4a63SDavid du Colombier 	case UniversalString:
528*8ccd4a63SDavid du Colombier 	case BMPString:
529*8ccd4a63SDavid du Colombier 		/* TODO: figure out when character set conversion is necessary */
530*8ccd4a63SDavid du Colombier 		err = octet_decode(&p, pend, length, isconstr, &va);
531*8ccd4a63SDavid du Colombier 		if(err == ASN_OK) {
532*8ccd4a63SDavid du Colombier 			pval->tag = VString;
533*8ccd4a63SDavid du Colombier 			pval->u.stringval = (char*)emalloc(va->len+1);
534*8ccd4a63SDavid du Colombier 			memmove(pval->u.stringval, va->data, va->len);
535*8ccd4a63SDavid du Colombier 			pval->u.stringval[va->len] = 0;
536*8ccd4a63SDavid du Colombier 			free(va);
537*8ccd4a63SDavid du Colombier 		}
538*8ccd4a63SDavid du Colombier 		break;
539*8ccd4a63SDavid du Colombier 
540*8ccd4a63SDavid du Colombier 	default:
541*8ccd4a63SDavid du Colombier 		if(p+length > pend)
542*8ccd4a63SDavid du Colombier 			err = ASN_EVALLEN;
543*8ccd4a63SDavid du Colombier 		else {
544*8ccd4a63SDavid du Colombier 			pval->tag = VOther;
545*8ccd4a63SDavid du Colombier 			pval->u.otherval = makebytes(p, length);
546*8ccd4a63SDavid du Colombier 			p += length;
547*8ccd4a63SDavid du Colombier 		}
548*8ccd4a63SDavid du Colombier 		break;
549*8ccd4a63SDavid du Colombier 	}
550*8ccd4a63SDavid du Colombier 	*pp = p;
551*8ccd4a63SDavid du Colombier 	return err;
552*8ccd4a63SDavid du Colombier }
553*8ccd4a63SDavid du Colombier 
554*8ccd4a63SDavid du Colombier /*
555*8ccd4a63SDavid du Colombier  * Decode an int in format where count bytes are
556*8ccd4a63SDavid du Colombier  * concatenated to form value.
557*8ccd4a63SDavid du Colombier  * Although ASN1 allows any size integer, we return
558*8ccd4a63SDavid du Colombier  * an error if the result doesn't fit in a 32-bit int.
559*8ccd4a63SDavid du Colombier  * If unsgned is not set, make sure to propagate sign bit.
560*8ccd4a63SDavid du Colombier  */
561*8ccd4a63SDavid du Colombier static int
int_decode(uchar ** pp,uchar * pend,int count,int unsgned,int * pint)562*8ccd4a63SDavid du Colombier int_decode(uchar** pp, uchar* pend, int count, int unsgned, int* pint)
563*8ccd4a63SDavid du Colombier {
564*8ccd4a63SDavid du Colombier 	int err;
565*8ccd4a63SDavid du Colombier 	int num;
566*8ccd4a63SDavid du Colombier 	uchar* p;
567*8ccd4a63SDavid du Colombier 
568*8ccd4a63SDavid du Colombier 	p = *pp;
569*8ccd4a63SDavid du Colombier 	err = ASN_OK;
570*8ccd4a63SDavid du Colombier 	num = 0;
571*8ccd4a63SDavid du Colombier 	if(p+count <= pend) {
572*8ccd4a63SDavid du Colombier 		if((count > 4) || (unsgned && count == 4 && (*p&0x80)))
573*8ccd4a63SDavid du Colombier 			err = ASN_ETOOBIG;
574*8ccd4a63SDavid du Colombier 		else {
575*8ccd4a63SDavid du Colombier 			if(!unsgned && count > 0 && count < 4 && (*p&0x80))
576*8ccd4a63SDavid du Colombier 				num = -1;		// set all bits, initially
577*8ccd4a63SDavid du Colombier 			while(count--)
578*8ccd4a63SDavid du Colombier 				num = (num << 8)|(*p++);
579*8ccd4a63SDavid du Colombier 		}
580*8ccd4a63SDavid du Colombier 	}
581*8ccd4a63SDavid du Colombier 	else
582*8ccd4a63SDavid du Colombier 		err = ASN_ESHORT;
583*8ccd4a63SDavid du Colombier 	*pint = num;
584*8ccd4a63SDavid du Colombier 	*pp = p;
585*8ccd4a63SDavid du Colombier 	return err;
586*8ccd4a63SDavid du Colombier }
587*8ccd4a63SDavid du Colombier 
588*8ccd4a63SDavid du Colombier /*
589*8ccd4a63SDavid du Colombier  * Decode an unsigned int in format where each
590*8ccd4a63SDavid du Colombier  * byte except last has high bit set, and remaining
591*8ccd4a63SDavid du Colombier  * seven bits of each byte are concatenated to form value.
592*8ccd4a63SDavid du Colombier  * Although ASN1 allows any size integer, we return
593*8ccd4a63SDavid du Colombier  * an error if the result doesn't fit in a 32 bit int.
594*8ccd4a63SDavid du Colombier  */
595*8ccd4a63SDavid du Colombier static int
uint7_decode(uchar ** pp,uchar * pend,int * pint)596*8ccd4a63SDavid du Colombier uint7_decode(uchar** pp, uchar* pend, int* pint)
597*8ccd4a63SDavid du Colombier {
598*8ccd4a63SDavid du Colombier 	int err;
599*8ccd4a63SDavid du Colombier 	int num;
600*8ccd4a63SDavid du Colombier 	int more;
601*8ccd4a63SDavid du Colombier 	int v;
602*8ccd4a63SDavid du Colombier 	uchar* p;
603*8ccd4a63SDavid du Colombier 
604*8ccd4a63SDavid du Colombier 	p = *pp;
605*8ccd4a63SDavid du Colombier 	err = ASN_OK;
606*8ccd4a63SDavid du Colombier 	num = 0;
607*8ccd4a63SDavid du Colombier 	more = 1;
608*8ccd4a63SDavid du Colombier 	while(more && p < pend) {
609*8ccd4a63SDavid du Colombier 		v = *p++;
610*8ccd4a63SDavid du Colombier 		if(num&0x7F000000) {
611*8ccd4a63SDavid du Colombier 			err = ASN_ETOOBIG;
612*8ccd4a63SDavid du Colombier 			break;
613*8ccd4a63SDavid du Colombier 		}
614*8ccd4a63SDavid du Colombier 		num <<= 7;
615*8ccd4a63SDavid du Colombier 		more = v&0x80;
616*8ccd4a63SDavid du Colombier 		num |= (v&0x7F);
617*8ccd4a63SDavid du Colombier 	}
618*8ccd4a63SDavid du Colombier 	if(p == pend)
619*8ccd4a63SDavid du Colombier 		err = ASN_ESHORT;
620*8ccd4a63SDavid du Colombier 	*pint = num;
621*8ccd4a63SDavid du Colombier 	*pp = p;
622*8ccd4a63SDavid du Colombier 	return err;
623*8ccd4a63SDavid du Colombier }
624*8ccd4a63SDavid du Colombier 
625*8ccd4a63SDavid du Colombier /*
626*8ccd4a63SDavid du Colombier  * Decode an octet string, recursively if isconstr.
627*8ccd4a63SDavid du Colombier  * We've already checked that length==-1 implies isconstr==1,
628*8ccd4a63SDavid du Colombier  * and otherwise that specified length fits within (*pp..pend)
629*8ccd4a63SDavid du Colombier  */
630*8ccd4a63SDavid du Colombier static int
octet_decode(uchar ** pp,uchar * pend,int length,int isconstr,Bytes ** pbytes)631*8ccd4a63SDavid du Colombier octet_decode(uchar** pp, uchar* pend, int length, int isconstr, Bytes** pbytes)
632*8ccd4a63SDavid du Colombier {
633*8ccd4a63SDavid du Colombier 	int err;
634*8ccd4a63SDavid du Colombier 	uchar* p;
635*8ccd4a63SDavid du Colombier 	Bytes* ans;
636*8ccd4a63SDavid du Colombier 	Bytes* newans;
637*8ccd4a63SDavid du Colombier 	uchar* pstart;
638*8ccd4a63SDavid du Colombier 	uchar* pold;
639*8ccd4a63SDavid du Colombier 	Elem	elem;
640*8ccd4a63SDavid du Colombier 
641*8ccd4a63SDavid du Colombier 	err = ASN_OK;
642*8ccd4a63SDavid du Colombier 	p = *pp;
643*8ccd4a63SDavid du Colombier 	ans = nil;
644*8ccd4a63SDavid du Colombier 	if(length >= 0 && !isconstr) {
645*8ccd4a63SDavid du Colombier 		ans = makebytes(p, length);
646*8ccd4a63SDavid du Colombier 		p += length;
647*8ccd4a63SDavid du Colombier 	}
648*8ccd4a63SDavid du Colombier 	else {
649*8ccd4a63SDavid du Colombier 		/* constructed, either definite or indefinite length */
650*8ccd4a63SDavid du Colombier 		pstart = p;
651*8ccd4a63SDavid du Colombier 		for(;;) {
652*8ccd4a63SDavid du Colombier 			if(length >= 0 && p >= pstart + length) {
653*8ccd4a63SDavid du Colombier 				if(p != pstart + length)
654*8ccd4a63SDavid du Colombier 					err = ASN_EVALLEN;
655*8ccd4a63SDavid du Colombier 				break;
656*8ccd4a63SDavid du Colombier 			}
657*8ccd4a63SDavid du Colombier 			pold = p;
658*8ccd4a63SDavid du Colombier 			err = ber_decode(&p, pend, &elem);
659*8ccd4a63SDavid du Colombier 			if(err != ASN_OK)
660*8ccd4a63SDavid du Colombier 				break;
661*8ccd4a63SDavid du Colombier 			switch(elem.val.tag) {
662*8ccd4a63SDavid du Colombier 			case VOctets:
663*8ccd4a63SDavid du Colombier 				newans = catbytes(ans, elem.val.u.octetsval);
664*8ccd4a63SDavid du Colombier 				freebytes(ans);
665*8ccd4a63SDavid du Colombier 				ans = newans;
666*8ccd4a63SDavid du Colombier 				break;
667*8ccd4a63SDavid du Colombier 
668*8ccd4a63SDavid du Colombier 			case VEOC:
669*8ccd4a63SDavid du Colombier 				if(length != -1) {
670*8ccd4a63SDavid du Colombier 					p = pold;
671*8ccd4a63SDavid du Colombier 					err = ASN_EINVAL;
672*8ccd4a63SDavid du Colombier 				}
673*8ccd4a63SDavid du Colombier 				goto cloop_done;
674*8ccd4a63SDavid du Colombier 
675*8ccd4a63SDavid du Colombier 			default:
676*8ccd4a63SDavid du Colombier 				p = pold;
677*8ccd4a63SDavid du Colombier 				err = ASN_EINVAL;
678*8ccd4a63SDavid du Colombier 				goto cloop_done;
679*8ccd4a63SDavid du Colombier 			}
680*8ccd4a63SDavid du Colombier 		}
681*8ccd4a63SDavid du Colombier cloop_done:
682*8ccd4a63SDavid du Colombier 		;
683*8ccd4a63SDavid du Colombier 	}
684*8ccd4a63SDavid du Colombier 	*pp = p;
685*8ccd4a63SDavid du Colombier 	*pbytes = ans;
686*8ccd4a63SDavid du Colombier 	return err;
687*8ccd4a63SDavid du Colombier }
688*8ccd4a63SDavid du Colombier 
689*8ccd4a63SDavid du Colombier /*
690*8ccd4a63SDavid du Colombier  * Decode a sequence or set.
691*8ccd4a63SDavid du Colombier  * We've already checked that length==-1 implies isconstr==1,
692*8ccd4a63SDavid du Colombier  * and otherwise that specified length fits within (*p..pend)
693*8ccd4a63SDavid du Colombier  */
694*8ccd4a63SDavid du Colombier static int
seq_decode(uchar ** pp,uchar * pend,int length,int isconstr,Elist ** pelist)695*8ccd4a63SDavid du Colombier seq_decode(uchar** pp, uchar* pend, int length, int isconstr, Elist** pelist)
696*8ccd4a63SDavid du Colombier {
697*8ccd4a63SDavid du Colombier 	int err;
698*8ccd4a63SDavid du Colombier 	uchar* p;
699*8ccd4a63SDavid du Colombier 	uchar* pstart;
700*8ccd4a63SDavid du Colombier 	uchar* pold;
701*8ccd4a63SDavid du Colombier 	Elist* ans;
702*8ccd4a63SDavid du Colombier 	Elem elem;
703*8ccd4a63SDavid du Colombier 	Elist* lve;
704*8ccd4a63SDavid du Colombier 	Elist* lveold;
705*8ccd4a63SDavid du Colombier 
706*8ccd4a63SDavid du Colombier 	err = ASN_OK;
707*8ccd4a63SDavid du Colombier 	ans = nil;
708*8ccd4a63SDavid du Colombier 	p = *pp;
709*8ccd4a63SDavid du Colombier 	if(!isconstr)
710*8ccd4a63SDavid du Colombier 		err = ASN_EPRIM;
711*8ccd4a63SDavid du Colombier 	else {
712*8ccd4a63SDavid du Colombier 		/* constructed, either definite or indefinite length */
713*8ccd4a63SDavid du Colombier 		lve = nil;
714*8ccd4a63SDavid du Colombier 		pstart = p;
715*8ccd4a63SDavid du Colombier 		for(;;) {
716*8ccd4a63SDavid du Colombier 			if(length >= 0 && p >= pstart + length) {
717*8ccd4a63SDavid du Colombier 				if(p != pstart + length)
718*8ccd4a63SDavid du Colombier 					err = ASN_EVALLEN;
719*8ccd4a63SDavid du Colombier 				break;
720*8ccd4a63SDavid du Colombier 			}
721*8ccd4a63SDavid du Colombier 			pold = p;
722*8ccd4a63SDavid du Colombier 			err = ber_decode(&p, pend, &elem);
723*8ccd4a63SDavid du Colombier 			if(err != ASN_OK)
724*8ccd4a63SDavid du Colombier 				break;
725*8ccd4a63SDavid du Colombier 			if(elem.val.tag == VEOC) {
726*8ccd4a63SDavid du Colombier 				if(length != -1) {
727*8ccd4a63SDavid du Colombier 					p = pold;
728*8ccd4a63SDavid du Colombier 					err = ASN_EINVAL;
729*8ccd4a63SDavid du Colombier 				}
730*8ccd4a63SDavid du Colombier 				break;
731*8ccd4a63SDavid du Colombier 			}
732*8ccd4a63SDavid du Colombier 			else
733*8ccd4a63SDavid du Colombier 				lve = mkel(elem, lve);
734*8ccd4a63SDavid du Colombier 		}
735*8ccd4a63SDavid du Colombier 		if(err == ASN_OK) {
736*8ccd4a63SDavid du Colombier 			/* reverse back to original order */
737*8ccd4a63SDavid du Colombier 			while(lve != nil) {
738*8ccd4a63SDavid du Colombier 				lveold = lve;
739*8ccd4a63SDavid du Colombier 				lve = lve->tl;
740*8ccd4a63SDavid du Colombier 				lveold->tl = ans;
741*8ccd4a63SDavid du Colombier 				ans = lveold;
742*8ccd4a63SDavid du Colombier 			}
743*8ccd4a63SDavid du Colombier 		}
744*8ccd4a63SDavid du Colombier 	}
745*8ccd4a63SDavid du Colombier 	*pp = p;
746*8ccd4a63SDavid du Colombier 	*pelist = ans;
747*8ccd4a63SDavid du Colombier 	return err;
748*8ccd4a63SDavid du Colombier }
749*8ccd4a63SDavid du Colombier 
750*8ccd4a63SDavid du Colombier /*
751*8ccd4a63SDavid du Colombier  * Encode e by BER rules, putting answer in *pbytes.
752*8ccd4a63SDavid du Colombier  * This is done by first calling enc with lenonly==1
753*8ccd4a63SDavid du Colombier  * to get the length of the needed buffer,
754*8ccd4a63SDavid du Colombier  * then allocating the buffer and using enc again to fill it up.
755*8ccd4a63SDavid du Colombier  */
756*8ccd4a63SDavid du Colombier static int
encode(Elem e,Bytes ** pbytes)757*8ccd4a63SDavid du Colombier encode(Elem e, Bytes** pbytes)
758*8ccd4a63SDavid du Colombier {
759*8ccd4a63SDavid du Colombier 	uchar* p;
760*8ccd4a63SDavid du Colombier 	Bytes* ans;
761*8ccd4a63SDavid du Colombier 	int err;
762*8ccd4a63SDavid du Colombier 	uchar uc;
763*8ccd4a63SDavid du Colombier 
764*8ccd4a63SDavid du Colombier 	p = &uc;
765*8ccd4a63SDavid du Colombier 	err = enc(&p, e, 1);
766*8ccd4a63SDavid du Colombier 	if(err == ASN_OK) {
767*8ccd4a63SDavid du Colombier 		ans = newbytes(p-&uc);
768*8ccd4a63SDavid du Colombier 		p = ans->data;
769*8ccd4a63SDavid du Colombier 		err = enc(&p, e, 0);
770*8ccd4a63SDavid du Colombier 		*pbytes = ans;
771*8ccd4a63SDavid du Colombier 	}
772*8ccd4a63SDavid du Colombier 	return err;
773*8ccd4a63SDavid du Colombier }
774*8ccd4a63SDavid du Colombier 
775*8ccd4a63SDavid du Colombier /*
776*8ccd4a63SDavid du Colombier  * The various enc functions take a pointer to a pointer
777*8ccd4a63SDavid du Colombier  * into a buffer, and encode their entity starting there,
778*8ccd4a63SDavid du Colombier  * updating the pointer afterwards.
779*8ccd4a63SDavid du Colombier  * If lenonly is 1, only the pointer update is done,
780*8ccd4a63SDavid du Colombier  * allowing enc to be called first to calculate the needed
781*8ccd4a63SDavid du Colombier  * buffer length.
782*8ccd4a63SDavid du Colombier  * If lenonly is 0, it is assumed that the answer will fit.
783*8ccd4a63SDavid du Colombier  */
784*8ccd4a63SDavid du Colombier 
785*8ccd4a63SDavid du Colombier static int
enc(uchar ** pp,Elem e,int lenonly)786*8ccd4a63SDavid du Colombier enc(uchar** pp, Elem e, int lenonly)
787*8ccd4a63SDavid du Colombier {
788*8ccd4a63SDavid du Colombier 	int err;
789*8ccd4a63SDavid du Colombier 	int vlen;
790*8ccd4a63SDavid du Colombier 	int constr;
791*8ccd4a63SDavid du Colombier 	Tag tag;
792*8ccd4a63SDavid du Colombier 	int v;
793*8ccd4a63SDavid du Colombier 	int ilen;
794*8ccd4a63SDavid du Colombier 	uchar* p;
795*8ccd4a63SDavid du Colombier 	uchar* psave;
796*8ccd4a63SDavid du Colombier 
797*8ccd4a63SDavid du Colombier 	p = *pp;
798*8ccd4a63SDavid du Colombier 	err = val_enc(&p, e, &constr, 1);
799*8ccd4a63SDavid du Colombier 	if(err != ASN_OK)
800*8ccd4a63SDavid du Colombier 		return err;
801*8ccd4a63SDavid du Colombier 	vlen = p - *pp;
802*8ccd4a63SDavid du Colombier 	p = *pp;
803*8ccd4a63SDavid du Colombier 	tag = e.tag;
804*8ccd4a63SDavid du Colombier 	v = tag.class|constr;
805*8ccd4a63SDavid du Colombier 	if(tag.num < 31) {
806*8ccd4a63SDavid du Colombier 		if(!lenonly)
807*8ccd4a63SDavid du Colombier 			*p = (v|tag.num);
808*8ccd4a63SDavid du Colombier 		p++;
809*8ccd4a63SDavid du Colombier 	}
810*8ccd4a63SDavid du Colombier 	else {
811*8ccd4a63SDavid du Colombier 		if(!lenonly)
812*8ccd4a63SDavid du Colombier 			*p = (v|31);
813*8ccd4a63SDavid du Colombier 		p++;
814*8ccd4a63SDavid du Colombier 		if(tag.num < 0)
815*8ccd4a63SDavid du Colombier 			return ASN_EINVAL;
816*8ccd4a63SDavid du Colombier 		uint7_enc(&p, tag.num, lenonly);
817*8ccd4a63SDavid du Colombier 	}
818*8ccd4a63SDavid du Colombier 	if(vlen < 0x80) {
819*8ccd4a63SDavid du Colombier 		if(!lenonly)
820*8ccd4a63SDavid du Colombier 			*p = vlen;
821*8ccd4a63SDavid du Colombier 		p++;
822*8ccd4a63SDavid du Colombier 	}
823*8ccd4a63SDavid du Colombier 	else {
824*8ccd4a63SDavid du Colombier 		psave = p;
825*8ccd4a63SDavid du Colombier 		int_enc(&p, vlen, 1, 1);
826*8ccd4a63SDavid du Colombier 		ilen = p-psave;
827*8ccd4a63SDavid du Colombier 		p = psave;
828*8ccd4a63SDavid du Colombier 		if(!lenonly) {
829*8ccd4a63SDavid du Colombier 			*p++ = (0x80 | ilen);
830*8ccd4a63SDavid du Colombier 			int_enc(&p, vlen, 1, 0);
831*8ccd4a63SDavid du Colombier 		}
832*8ccd4a63SDavid du Colombier 		else
833*8ccd4a63SDavid du Colombier 			p += 1 + ilen;
834*8ccd4a63SDavid du Colombier 	}
835*8ccd4a63SDavid du Colombier 	if(!lenonly)
836*8ccd4a63SDavid du Colombier 		val_enc(&p, e, &constr, 0);
837*8ccd4a63SDavid du Colombier 	else
838*8ccd4a63SDavid du Colombier 		p += vlen;
839*8ccd4a63SDavid du Colombier 	*pp = p;
840*8ccd4a63SDavid du Colombier 	return err;
841*8ccd4a63SDavid du Colombier }
842*8ccd4a63SDavid du Colombier 
843*8ccd4a63SDavid du Colombier static int
val_enc(uchar ** pp,Elem e,int * pconstr,int lenonly)844*8ccd4a63SDavid du Colombier val_enc(uchar** pp, Elem e, int *pconstr, int lenonly)
845*8ccd4a63SDavid du Colombier {
846*8ccd4a63SDavid du Colombier 	int err;
847*8ccd4a63SDavid du Colombier 	uchar* p;
848*8ccd4a63SDavid du Colombier 	int kind;
849*8ccd4a63SDavid du Colombier 	int cl;
850*8ccd4a63SDavid du Colombier 	int v;
851*8ccd4a63SDavid du Colombier 	Bytes* bb = nil;
852*8ccd4a63SDavid du Colombier 	Bits* bits;
853*8ccd4a63SDavid du Colombier 	Ints* oid;
854*8ccd4a63SDavid du Colombier 	int k;
855*8ccd4a63SDavid du Colombier 	Elist* el;
856*8ccd4a63SDavid du Colombier 	char* s;
857*8ccd4a63SDavid du Colombier 
858*8ccd4a63SDavid du Colombier 	p = *pp;
859*8ccd4a63SDavid du Colombier 	err = ASN_OK;
860*8ccd4a63SDavid du Colombier 	kind = e.tag.num;
861*8ccd4a63SDavid du Colombier 	cl = e.tag.class;
862*8ccd4a63SDavid du Colombier 	*pconstr = 0;
863*8ccd4a63SDavid du Colombier 	if(cl != Universal) {
864*8ccd4a63SDavid du Colombier 		switch(e.val.tag) {
865*8ccd4a63SDavid du Colombier 		case VBool:
866*8ccd4a63SDavid du Colombier 			kind = BOOLEAN;
867*8ccd4a63SDavid du Colombier 			break;
868*8ccd4a63SDavid du Colombier 		case VInt:
869*8ccd4a63SDavid du Colombier 			kind = INTEGER;
870*8ccd4a63SDavid du Colombier 			break;
871*8ccd4a63SDavid du Colombier 		case VBigInt:
872*8ccd4a63SDavid du Colombier 			kind = INTEGER;
873*8ccd4a63SDavid du Colombier 			break;
874*8ccd4a63SDavid du Colombier 		case VOctets:
875*8ccd4a63SDavid du Colombier 			kind = OCTET_STRING;
876*8ccd4a63SDavid du Colombier 			break;
877*8ccd4a63SDavid du Colombier 		case VReal:
878*8ccd4a63SDavid du Colombier 			kind = REAL;
879*8ccd4a63SDavid du Colombier 			break;
880*8ccd4a63SDavid du Colombier 		case VOther:
881*8ccd4a63SDavid du Colombier 			kind = OCTET_STRING;
882*8ccd4a63SDavid du Colombier 			break;
883*8ccd4a63SDavid du Colombier 		case VBitString:
884*8ccd4a63SDavid du Colombier 			kind = BIT_STRING;
885*8ccd4a63SDavid du Colombier 			break;
886*8ccd4a63SDavid du Colombier 		case VNull:
887*8ccd4a63SDavid du Colombier 			kind = NULLTAG;
888*8ccd4a63SDavid du Colombier 			break;
889*8ccd4a63SDavid du Colombier 		case VObjId:
890*8ccd4a63SDavid du Colombier 			kind = OBJECT_ID;
891*8ccd4a63SDavid du Colombier 			break;
892*8ccd4a63SDavid du Colombier 		case VString:
893*8ccd4a63SDavid du Colombier 			kind = UniversalString;
894*8ccd4a63SDavid du Colombier 			break;
895*8ccd4a63SDavid du Colombier 		case VSeq:
896*8ccd4a63SDavid du Colombier 			kind = SEQUENCE;
897*8ccd4a63SDavid du Colombier 			break;
898*8ccd4a63SDavid du Colombier 		case VSet:
899*8ccd4a63SDavid du Colombier 			kind = SETOF;
900*8ccd4a63SDavid du Colombier 			break;
901*8ccd4a63SDavid du Colombier 		}
902*8ccd4a63SDavid du Colombier 	}
903*8ccd4a63SDavid du Colombier 	switch(kind) {
904*8ccd4a63SDavid du Colombier 	case BOOLEAN:
905*8ccd4a63SDavid du Colombier 		if(is_int(&e, &v)) {
906*8ccd4a63SDavid du Colombier 			if(v != 0)
907*8ccd4a63SDavid du Colombier 				v = 255;
908*8ccd4a63SDavid du Colombier 			 int_enc(&p, v, 1, lenonly);
909*8ccd4a63SDavid du Colombier 		}
910*8ccd4a63SDavid du Colombier 		else
911*8ccd4a63SDavid du Colombier 			err = ASN_EINVAL;
912*8ccd4a63SDavid du Colombier 		break;
913*8ccd4a63SDavid du Colombier 
914*8ccd4a63SDavid du Colombier 	case INTEGER:
915*8ccd4a63SDavid du Colombier 	case ENUMERATED:
916*8ccd4a63SDavid du Colombier 		if(is_int(&e, &v))
917*8ccd4a63SDavid du Colombier 			int_enc(&p, v, 0, lenonly);
918*8ccd4a63SDavid du Colombier 		else {
919*8ccd4a63SDavid du Colombier 			if(is_bigint(&e, &bb)) {
920*8ccd4a63SDavid du Colombier 				if(!lenonly)
921*8ccd4a63SDavid du Colombier 					memmove(p, bb->data, bb->len);
922*8ccd4a63SDavid du Colombier 				p += bb->len;
923*8ccd4a63SDavid du Colombier 			}
924*8ccd4a63SDavid du Colombier 			else
925*8ccd4a63SDavid du Colombier 				err = ASN_EINVAL;
926*8ccd4a63SDavid du Colombier 		}
927*8ccd4a63SDavid du Colombier 		break;
928*8ccd4a63SDavid du Colombier 
929*8ccd4a63SDavid du Colombier 	case BIT_STRING:
930*8ccd4a63SDavid du Colombier 		if(is_bitstring(&e, &bits)) {
931*8ccd4a63SDavid du Colombier 			if(bits->len == 0) {
932*8ccd4a63SDavid du Colombier 				if(!lenonly)
933*8ccd4a63SDavid du Colombier 					*p = 0;
934*8ccd4a63SDavid du Colombier 				p++;
935*8ccd4a63SDavid du Colombier 			}
936*8ccd4a63SDavid du Colombier 			else {
937*8ccd4a63SDavid du Colombier 				v = bits->unusedbits;
938*8ccd4a63SDavid du Colombier 				if(v < 0 || v > 7)
939*8ccd4a63SDavid du Colombier 					err = ASN_EINVAL;
940*8ccd4a63SDavid du Colombier 				else {
941*8ccd4a63SDavid du Colombier 					if(!lenonly) {
942*8ccd4a63SDavid du Colombier 						*p = v;
943*8ccd4a63SDavid du Colombier 						memmove(p+1, bits->data, bits->len);
944*8ccd4a63SDavid du Colombier 					}
945*8ccd4a63SDavid du Colombier 					p += 1 + bits->len;
946*8ccd4a63SDavid du Colombier 				}
947*8ccd4a63SDavid du Colombier 			}
948*8ccd4a63SDavid du Colombier 		}
949*8ccd4a63SDavid du Colombier 		else
950*8ccd4a63SDavid du Colombier 			err = ASN_EINVAL;
951*8ccd4a63SDavid du Colombier 		break;
952*8ccd4a63SDavid du Colombier 
953*8ccd4a63SDavid du Colombier 	case OCTET_STRING:
954*8ccd4a63SDavid du Colombier 	case ObjectDescriptor:
955*8ccd4a63SDavid du Colombier 	case EXTERNAL:
956*8ccd4a63SDavid du Colombier 	case REAL:
957*8ccd4a63SDavid du Colombier 	case EMBEDDED_PDV:
958*8ccd4a63SDavid du Colombier 		bb = nil;
959*8ccd4a63SDavid du Colombier 		switch(e.val.tag) {
960*8ccd4a63SDavid du Colombier 		case VOctets:
961*8ccd4a63SDavid du Colombier 			bb = e.val.u.octetsval;
962*8ccd4a63SDavid du Colombier 			break;
963*8ccd4a63SDavid du Colombier 		case VReal:
964*8ccd4a63SDavid du Colombier 			bb = e.val.u.realval;
965*8ccd4a63SDavid du Colombier 			break;
966*8ccd4a63SDavid du Colombier 		case VOther:
967*8ccd4a63SDavid du Colombier 			bb = e.val.u.otherval;
968*8ccd4a63SDavid du Colombier 			break;
969*8ccd4a63SDavid du Colombier 		}
970*8ccd4a63SDavid du Colombier 		if(bb != nil) {
971*8ccd4a63SDavid du Colombier 			if(!lenonly)
972*8ccd4a63SDavid du Colombier 				memmove(p, bb->data, bb->len);
973*8ccd4a63SDavid du Colombier 			p += bb->len;
974*8ccd4a63SDavid du Colombier 		}
975*8ccd4a63SDavid du Colombier 			else
976*8ccd4a63SDavid du Colombier 				err = ASN_EINVAL;
977*8ccd4a63SDavid du Colombier 		break;
978*8ccd4a63SDavid du Colombier 
979*8ccd4a63SDavid du Colombier 	case NULLTAG:
980*8ccd4a63SDavid du Colombier 		break;
981*8ccd4a63SDavid du Colombier 
982*8ccd4a63SDavid du Colombier 	case OBJECT_ID:
983*8ccd4a63SDavid du Colombier 		if(is_oid(&e, &oid)) {
984*8ccd4a63SDavid du Colombier 			for(k = 0; k < oid->len; k++) {
985*8ccd4a63SDavid du Colombier 				v = oid->data[k];
986*8ccd4a63SDavid du Colombier 				if(k == 0) {
987*8ccd4a63SDavid du Colombier 					v *= 40;
988*8ccd4a63SDavid du Colombier 					if(oid->len > 1)
989*8ccd4a63SDavid du Colombier 						v += oid->data[++k];
990*8ccd4a63SDavid du Colombier 				}
991*8ccd4a63SDavid du Colombier 				uint7_enc(&p, v, lenonly);
992*8ccd4a63SDavid du Colombier 			}
993*8ccd4a63SDavid du Colombier 		}
994*8ccd4a63SDavid du Colombier 		else
995*8ccd4a63SDavid du Colombier 			err = ASN_EINVAL;
996*8ccd4a63SDavid du Colombier 		break;
997*8ccd4a63SDavid du Colombier 
998*8ccd4a63SDavid du Colombier 	case SEQUENCE:
999*8ccd4a63SDavid du Colombier 	case SETOF:
1000*8ccd4a63SDavid du Colombier 		el = nil;
1001*8ccd4a63SDavid du Colombier 		if(e.val.tag == VSeq)
1002*8ccd4a63SDavid du Colombier 			el = e.val.u.seqval;
1003*8ccd4a63SDavid du Colombier 		else if(e.val.tag == VSet)
1004*8ccd4a63SDavid du Colombier 			el = e.val.u.setval;
1005*8ccd4a63SDavid du Colombier 		else
1006*8ccd4a63SDavid du Colombier 			err = ASN_EINVAL;
1007*8ccd4a63SDavid du Colombier 		if(el != nil) {
1008*8ccd4a63SDavid du Colombier 			*pconstr = CONSTR_MASK;
1009*8ccd4a63SDavid du Colombier 			for(; el != nil; el = el->tl) {
1010*8ccd4a63SDavid du Colombier 				err = enc(&p, el->hd, lenonly);
1011*8ccd4a63SDavid du Colombier 				if(err != ASN_OK)
1012*8ccd4a63SDavid du Colombier 					break;
1013*8ccd4a63SDavid du Colombier 			}
1014*8ccd4a63SDavid du Colombier 		}
1015*8ccd4a63SDavid du Colombier 		break;
1016*8ccd4a63SDavid du Colombier 
1017*8ccd4a63SDavid du Colombier 	case NumericString:
1018*8ccd4a63SDavid du Colombier 	case PrintableString:
1019*8ccd4a63SDavid du Colombier 	case TeletexString:
1020*8ccd4a63SDavid du Colombier 	case VideotexString:
1021*8ccd4a63SDavid du Colombier 	case IA5String:
1022*8ccd4a63SDavid du Colombier 	case UTCTime:
1023*8ccd4a63SDavid du Colombier 	case GeneralizedTime:
1024*8ccd4a63SDavid du Colombier 	case GraphicString:
1025*8ccd4a63SDavid du Colombier 	case VisibleString:
1026*8ccd4a63SDavid du Colombier 	case GeneralString:
1027*8ccd4a63SDavid du Colombier 	case UniversalString:
1028*8ccd4a63SDavid du Colombier 	case BMPString:
1029*8ccd4a63SDavid du Colombier 		if(e.val.tag == VString) {
1030*8ccd4a63SDavid du Colombier 			s = e.val.u.stringval;
1031*8ccd4a63SDavid du Colombier 			if(s != nil) {
1032*8ccd4a63SDavid du Colombier 				v = strlen(s);
1033*8ccd4a63SDavid du Colombier 				if(!lenonly)
1034*8ccd4a63SDavid du Colombier 					memmove(p, s, v);
1035*8ccd4a63SDavid du Colombier 				p += v;
1036*8ccd4a63SDavid du Colombier 			}
1037*8ccd4a63SDavid du Colombier 		}
1038*8ccd4a63SDavid du Colombier 		else
1039*8ccd4a63SDavid du Colombier 			err = ASN_EINVAL;
1040*8ccd4a63SDavid du Colombier 		break;
1041*8ccd4a63SDavid du Colombier 
1042*8ccd4a63SDavid du Colombier 	default:
1043*8ccd4a63SDavid du Colombier 		err = ASN_EINVAL;
1044*8ccd4a63SDavid du Colombier 	}
1045*8ccd4a63SDavid du Colombier 	*pp = p;
1046*8ccd4a63SDavid du Colombier 	return err;
1047*8ccd4a63SDavid du Colombier }
1048*8ccd4a63SDavid du Colombier 
1049*8ccd4a63SDavid du Colombier /*
1050*8ccd4a63SDavid du Colombier  * Encode num as unsigned 7 bit values with top bit 1 on all bytes
1051*8ccd4a63SDavid du Colombier  * except last, only putting in bytes if !lenonly.
1052*8ccd4a63SDavid du Colombier  */
1053*8ccd4a63SDavid du Colombier static void
uint7_enc(uchar ** pp,int num,int lenonly)1054*8ccd4a63SDavid du Colombier uint7_enc(uchar** pp, int num, int lenonly)
1055*8ccd4a63SDavid du Colombier {
1056*8ccd4a63SDavid du Colombier 	int n;
1057*8ccd4a63SDavid du Colombier 	int v;
1058*8ccd4a63SDavid du Colombier 	int k;
1059*8ccd4a63SDavid du Colombier 	uchar* p;
1060*8ccd4a63SDavid du Colombier 
1061*8ccd4a63SDavid du Colombier 	p = *pp;
1062*8ccd4a63SDavid du Colombier 	n = 1;
1063*8ccd4a63SDavid du Colombier 	v = num >> 7;
1064*8ccd4a63SDavid du Colombier 	while(v > 0) {
1065*8ccd4a63SDavid du Colombier 		v >>= 7;
1066*8ccd4a63SDavid du Colombier 		n++;
1067*8ccd4a63SDavid du Colombier 	}
1068*8ccd4a63SDavid du Colombier 	if(lenonly)
1069*8ccd4a63SDavid du Colombier 		p += n;
1070*8ccd4a63SDavid du Colombier 	else {
1071*8ccd4a63SDavid du Colombier 		for(k = (n - 1)*7; k > 0; k -= 7)
1072*8ccd4a63SDavid du Colombier 			*p++= ((num >> k)|0x80);
1073*8ccd4a63SDavid du Colombier 		*p++ = (num&0x7F);
1074*8ccd4a63SDavid du Colombier 	}
1075*8ccd4a63SDavid du Colombier 	*pp = p;
1076*8ccd4a63SDavid du Colombier }
1077*8ccd4a63SDavid du Colombier 
1078*8ccd4a63SDavid du Colombier /*
1079*8ccd4a63SDavid du Colombier  * Encode num as unsigned or signed integer,
1080*8ccd4a63SDavid du Colombier  * only putting in bytes if !lenonly.
1081*8ccd4a63SDavid du Colombier  * Encoding is length followed by bytes to concatenate.
1082*8ccd4a63SDavid du Colombier  */
1083*8ccd4a63SDavid du Colombier static void
int_enc(uchar ** pp,int num,int unsgned,int lenonly)1084*8ccd4a63SDavid du Colombier int_enc(uchar** pp, int num, int unsgned, int lenonly)
1085*8ccd4a63SDavid du Colombier {
1086*8ccd4a63SDavid du Colombier 	int v;
1087*8ccd4a63SDavid du Colombier 	int n;
1088*8ccd4a63SDavid du Colombier 	int prevv;
1089*8ccd4a63SDavid du Colombier 	int k;
1090*8ccd4a63SDavid du Colombier 	uchar* p;
1091*8ccd4a63SDavid du Colombier 
1092*8ccd4a63SDavid du Colombier 	p = *pp;
1093*8ccd4a63SDavid du Colombier 	v = num;
1094*8ccd4a63SDavid du Colombier 	if(v < 0)
1095*8ccd4a63SDavid du Colombier 		v = -(v + 1);
1096*8ccd4a63SDavid du Colombier 	n = 1;
1097*8ccd4a63SDavid du Colombier 	prevv = v;
1098*8ccd4a63SDavid du Colombier 	v >>= 8;
1099*8ccd4a63SDavid du Colombier 	while(v > 0) {
1100*8ccd4a63SDavid du Colombier 		prevv = v;
1101*8ccd4a63SDavid du Colombier 		v >>= 8;
1102*8ccd4a63SDavid du Colombier 		n++;
1103*8ccd4a63SDavid du Colombier 	}
1104*8ccd4a63SDavid du Colombier 	if(!unsgned && (prevv&0x80))
1105*8ccd4a63SDavid du Colombier 		n++;
1106*8ccd4a63SDavid du Colombier 	if(lenonly)
1107*8ccd4a63SDavid du Colombier 		p += n;
1108*8ccd4a63SDavid du Colombier 	else {
1109*8ccd4a63SDavid du Colombier 		for(k = (n - 1)*8; k >= 0; k -= 8)
1110*8ccd4a63SDavid du Colombier 			*p++ = (num >> k);
1111*8ccd4a63SDavid du Colombier 	}
1112*8ccd4a63SDavid du Colombier 	*pp = p;
1113*8ccd4a63SDavid du Colombier }
1114*8ccd4a63SDavid du Colombier 
1115*8ccd4a63SDavid du Colombier static int
ints_eq(Ints * a,Ints * b)1116*8ccd4a63SDavid du Colombier ints_eq(Ints* a, Ints* b)
1117*8ccd4a63SDavid du Colombier {
1118*8ccd4a63SDavid du Colombier 	int	alen;
1119*8ccd4a63SDavid du Colombier 	int	i;
1120*8ccd4a63SDavid du Colombier 
1121*8ccd4a63SDavid du Colombier 	alen = a->len;
1122*8ccd4a63SDavid du Colombier 	if(alen != b->len)
1123*8ccd4a63SDavid du Colombier 		return 0;
1124*8ccd4a63SDavid du Colombier 	for(i = 0; i < alen; i++)
1125*8ccd4a63SDavid du Colombier 		if(a->data[i] != b->data[i])
1126*8ccd4a63SDavid du Colombier 			return 0;
1127*8ccd4a63SDavid du Colombier 	return 1;
1128*8ccd4a63SDavid du Colombier }
1129*8ccd4a63SDavid du Colombier 
1130*8ccd4a63SDavid du Colombier /*
1131*8ccd4a63SDavid du Colombier  * Look up o in tab (which must have nil entry to terminate).
1132*8ccd4a63SDavid du Colombier  * Return index of matching entry, or -1 if none.
1133*8ccd4a63SDavid du Colombier  */
1134*8ccd4a63SDavid du Colombier static int
oid_lookup(Ints * o,Ints ** tab)1135*8ccd4a63SDavid du Colombier oid_lookup(Ints* o, Ints** tab)
1136*8ccd4a63SDavid du Colombier {
1137*8ccd4a63SDavid du Colombier 	int i;
1138*8ccd4a63SDavid du Colombier 
1139*8ccd4a63SDavid du Colombier 	for(i = 0; tab[i] != nil; i++)
1140*8ccd4a63SDavid du Colombier 		if(ints_eq(o, tab[i]))
1141*8ccd4a63SDavid du Colombier 			return  i;
1142*8ccd4a63SDavid du Colombier 	return -1;
1143*8ccd4a63SDavid du Colombier }
1144*8ccd4a63SDavid du Colombier 
1145*8ccd4a63SDavid du Colombier /*
1146*8ccd4a63SDavid du Colombier  * Return true if *pe is a SEQUENCE, and set *pseq to
1147*8ccd4a63SDavid du Colombier  * the value of the sequence if so.
1148*8ccd4a63SDavid du Colombier  */
1149*8ccd4a63SDavid du Colombier static int
is_seq(Elem * pe,Elist ** pseq)1150*8ccd4a63SDavid du Colombier is_seq(Elem* pe, Elist** pseq)
1151*8ccd4a63SDavid du Colombier {
1152*8ccd4a63SDavid du Colombier 	if(pe->tag.class == Universal && pe->tag.num == SEQUENCE && pe->val.tag == VSeq) {
1153*8ccd4a63SDavid du Colombier 		*pseq = pe->val.u.seqval;
1154*8ccd4a63SDavid du Colombier 		return 1;
1155*8ccd4a63SDavid du Colombier 	}
1156*8ccd4a63SDavid du Colombier 	return 0;
1157*8ccd4a63SDavid du Colombier }
1158*8ccd4a63SDavid du Colombier 
1159*8ccd4a63SDavid du Colombier static int
is_set(Elem * pe,Elist ** pset)1160*8ccd4a63SDavid du Colombier is_set(Elem* pe, Elist** pset)
1161*8ccd4a63SDavid du Colombier {
1162*8ccd4a63SDavid du Colombier 	if(pe->tag.class == Universal && pe->tag.num == SETOF && pe->val.tag == VSet) {
1163*8ccd4a63SDavid du Colombier 		*pset = pe->val.u.setval;
1164*8ccd4a63SDavid du Colombier 		return 1;
1165*8ccd4a63SDavid du Colombier 	}
1166*8ccd4a63SDavid du Colombier 	return 0;
1167*8ccd4a63SDavid du Colombier }
1168*8ccd4a63SDavid du Colombier 
1169*8ccd4a63SDavid du Colombier static int
is_int(Elem * pe,int * pint)1170*8ccd4a63SDavid du Colombier is_int(Elem* pe, int* pint)
1171*8ccd4a63SDavid du Colombier {
1172*8ccd4a63SDavid du Colombier 	if(pe->tag.class == Universal) {
1173*8ccd4a63SDavid du Colombier 		if(pe->tag.num == INTEGER && pe->val.tag == VInt) {
1174*8ccd4a63SDavid du Colombier 			*pint = pe->val.u.intval;
1175*8ccd4a63SDavid du Colombier 			return 1;
1176*8ccd4a63SDavid du Colombier 		}
1177*8ccd4a63SDavid du Colombier 		else if(pe->tag.num == BOOLEAN && pe->val.tag == VBool) {
1178*8ccd4a63SDavid du Colombier 			*pint = pe->val.u.boolval;
1179*8ccd4a63SDavid du Colombier 			return 1;
1180*8ccd4a63SDavid du Colombier 		}
1181*8ccd4a63SDavid du Colombier 	}
1182*8ccd4a63SDavid du Colombier 	return 0;
1183*8ccd4a63SDavid du Colombier }
1184*8ccd4a63SDavid du Colombier 
1185*8ccd4a63SDavid du Colombier /*
1186*8ccd4a63SDavid du Colombier  * for convience, all VInt's are readable via this routine,
1187*8ccd4a63SDavid du Colombier  * as well as all VBigInt's
1188*8ccd4a63SDavid du Colombier  */
1189*8ccd4a63SDavid du Colombier static int
is_bigint(Elem * pe,Bytes ** pbigint)1190*8ccd4a63SDavid du Colombier is_bigint(Elem* pe, Bytes** pbigint)
1191*8ccd4a63SDavid du Colombier {
1192*8ccd4a63SDavid du Colombier 	int v, n, i;
1193*8ccd4a63SDavid du Colombier 
1194*8ccd4a63SDavid du Colombier 	if(pe->tag.class == Universal && pe->tag.num == INTEGER) {
1195*8ccd4a63SDavid du Colombier 		if(pe->val.tag == VBigInt)
1196*8ccd4a63SDavid du Colombier 			*pbigint = pe->val.u.bigintval;
1197*8ccd4a63SDavid du Colombier 		else if(pe->val.tag == VInt){
1198*8ccd4a63SDavid du Colombier 			v = pe->val.u.intval;
1199*8ccd4a63SDavid du Colombier 			for(n = 1; n < 4; n++)
1200*8ccd4a63SDavid du Colombier 				if((1 << (8 * n)) > v)
1201*8ccd4a63SDavid du Colombier 					break;
1202*8ccd4a63SDavid du Colombier 			*pbigint = newbytes(n);
1203*8ccd4a63SDavid du Colombier 			for(i = 0; i < n; i++)
1204*8ccd4a63SDavid du Colombier 				(*pbigint)->data[i] = (v >> ((n - 1 - i) * 8));
1205*8ccd4a63SDavid du Colombier 		}else
1206*8ccd4a63SDavid du Colombier 			return 0;
1207*8ccd4a63SDavid du Colombier 		return 1;
1208*8ccd4a63SDavid du Colombier 	}
1209*8ccd4a63SDavid du Colombier 	return 0;
1210*8ccd4a63SDavid du Colombier }
1211*8ccd4a63SDavid du Colombier 
1212*8ccd4a63SDavid du Colombier static int
is_bitstring(Elem * pe,Bits ** pbits)1213*8ccd4a63SDavid du Colombier is_bitstring(Elem* pe, Bits** pbits)
1214*8ccd4a63SDavid du Colombier {
1215*8ccd4a63SDavid du Colombier 	if(pe->tag.class == Universal && pe->tag.num == BIT_STRING && pe->val.tag == VBitString) {
1216*8ccd4a63SDavid du Colombier 		*pbits = pe->val.u.bitstringval;
1217*8ccd4a63SDavid du Colombier 		return 1;
1218*8ccd4a63SDavid du Colombier 	}
1219*8ccd4a63SDavid du Colombier 	return 0;
1220*8ccd4a63SDavid du Colombier }
1221*8ccd4a63SDavid du Colombier 
1222*8ccd4a63SDavid du Colombier static int
is_octetstring(Elem * pe,Bytes ** poctets)1223*8ccd4a63SDavid du Colombier is_octetstring(Elem* pe, Bytes** poctets)
1224*8ccd4a63SDavid du Colombier {
1225*8ccd4a63SDavid du Colombier 	if(pe->tag.class == Universal && pe->tag.num == OCTET_STRING && pe->val.tag == VOctets) {
1226*8ccd4a63SDavid du Colombier 		*poctets = pe->val.u.octetsval;
1227*8ccd4a63SDavid du Colombier 		return 1;
1228*8ccd4a63SDavid du Colombier 	}
1229*8ccd4a63SDavid du Colombier 	return 0;
1230*8ccd4a63SDavid du Colombier }
1231*8ccd4a63SDavid du Colombier 
1232*8ccd4a63SDavid du Colombier static int
is_oid(Elem * pe,Ints ** poid)1233*8ccd4a63SDavid du Colombier is_oid(Elem* pe, Ints** poid)
1234*8ccd4a63SDavid du Colombier {
1235*8ccd4a63SDavid du Colombier 	if(pe->tag.class == Universal && pe->tag.num == OBJECT_ID && pe->val.tag == VObjId) {
1236*8ccd4a63SDavid du Colombier 		*poid = pe->val.u.objidval;
1237*8ccd4a63SDavid du Colombier 		return 1;
1238*8ccd4a63SDavid du Colombier 	}
1239*8ccd4a63SDavid du Colombier 	return 0;
1240*8ccd4a63SDavid du Colombier }
1241*8ccd4a63SDavid du Colombier 
1242*8ccd4a63SDavid du Colombier static int
is_string(Elem * pe,char ** pstring)1243*8ccd4a63SDavid du Colombier is_string(Elem* pe, char** pstring)
1244*8ccd4a63SDavid du Colombier {
1245*8ccd4a63SDavid du Colombier 	if(pe->tag.class == Universal) {
1246*8ccd4a63SDavid du Colombier 		switch(pe->tag.num) {
1247*8ccd4a63SDavid du Colombier 		case NumericString:
1248*8ccd4a63SDavid du Colombier 		case PrintableString:
1249*8ccd4a63SDavid du Colombier 		case TeletexString:
1250*8ccd4a63SDavid du Colombier 		case VideotexString:
1251*8ccd4a63SDavid du Colombier 		case IA5String:
1252*8ccd4a63SDavid du Colombier 		case GraphicString:
1253*8ccd4a63SDavid du Colombier 		case VisibleString:
1254*8ccd4a63SDavid du Colombier 		case GeneralString:
1255*8ccd4a63SDavid du Colombier 		case UniversalString:
1256*8ccd4a63SDavid du Colombier 		case BMPString:
1257*8ccd4a63SDavid du Colombier 			if(pe->val.tag == VString) {
1258*8ccd4a63SDavid du Colombier 				*pstring = pe->val.u.stringval;
1259*8ccd4a63SDavid du Colombier 				return 1;
1260*8ccd4a63SDavid du Colombier 			}
1261*8ccd4a63SDavid du Colombier 		}
1262*8ccd4a63SDavid du Colombier 	}
1263*8ccd4a63SDavid du Colombier 	return 0;
1264*8ccd4a63SDavid du Colombier }
1265*8ccd4a63SDavid du Colombier 
1266*8ccd4a63SDavid du Colombier static int
is_time(Elem * pe,char ** ptime)1267*8ccd4a63SDavid du Colombier is_time(Elem* pe, char** ptime)
1268*8ccd4a63SDavid du Colombier {
1269*8ccd4a63SDavid du Colombier 	if(pe->tag.class == Universal
1270*8ccd4a63SDavid du Colombier 	   && (pe->tag.num == UTCTime || pe->tag.num == GeneralizedTime)
1271*8ccd4a63SDavid du Colombier 	   && pe->val.tag == VString) {
1272*8ccd4a63SDavid du Colombier 		*ptime = pe->val.u.stringval;
1273*8ccd4a63SDavid du Colombier 		return 1;
1274*8ccd4a63SDavid du Colombier 	}
1275*8ccd4a63SDavid du Colombier 	return 0;
1276*8ccd4a63SDavid du Colombier }
1277*8ccd4a63SDavid du Colombier 
1278*8ccd4a63SDavid du Colombier 
1279*8ccd4a63SDavid du Colombier /*
1280*8ccd4a63SDavid du Colombier  * malloc and return a new Bytes structure capable of
1281*8ccd4a63SDavid du Colombier  * holding len bytes. (len >= 0)
1282*8ccd4a63SDavid du Colombier  */
1283*8ccd4a63SDavid du Colombier static Bytes*
newbytes(int len)1284*8ccd4a63SDavid du Colombier newbytes(int len)
1285*8ccd4a63SDavid du Colombier {
1286*8ccd4a63SDavid du Colombier 	Bytes* ans;
1287*8ccd4a63SDavid du Colombier 
1288*8ccd4a63SDavid du Colombier 	ans = (Bytes*)emalloc(OFFSETOF(data[0], Bytes) + len);
1289*8ccd4a63SDavid du Colombier 	ans->len = len;
1290*8ccd4a63SDavid du Colombier 	return ans;
1291*8ccd4a63SDavid du Colombier }
1292*8ccd4a63SDavid du Colombier 
1293*8ccd4a63SDavid du Colombier /*
1294*8ccd4a63SDavid du Colombier  * newbytes(len), with data initialized from buf
1295*8ccd4a63SDavid du Colombier  */
1296*8ccd4a63SDavid du Colombier static Bytes*
makebytes(uchar * buf,int len)1297*8ccd4a63SDavid du Colombier makebytes(uchar* buf, int len)
1298*8ccd4a63SDavid du Colombier {
1299*8ccd4a63SDavid du Colombier 	Bytes* ans;
1300*8ccd4a63SDavid du Colombier 
1301*8ccd4a63SDavid du Colombier 	ans = newbytes(len);
1302*8ccd4a63SDavid du Colombier 	memmove(ans->data, buf, len);
1303*8ccd4a63SDavid du Colombier 	return ans;
1304*8ccd4a63SDavid du Colombier }
1305*8ccd4a63SDavid du Colombier 
1306*8ccd4a63SDavid du Colombier static void
freebytes(Bytes * b)1307*8ccd4a63SDavid du Colombier freebytes(Bytes* b)
1308*8ccd4a63SDavid du Colombier {
1309*8ccd4a63SDavid du Colombier 	if(b != nil)
1310*8ccd4a63SDavid du Colombier 		free(b);
1311*8ccd4a63SDavid du Colombier }
1312*8ccd4a63SDavid du Colombier 
1313*8ccd4a63SDavid du Colombier /*
1314*8ccd4a63SDavid du Colombier  * Make a new Bytes, containing bytes of b1 followed by those of b2.
1315*8ccd4a63SDavid du Colombier  * Either b1 or b2 or both can be nil.
1316*8ccd4a63SDavid du Colombier  */
1317*8ccd4a63SDavid du Colombier static Bytes*
catbytes(Bytes * b1,Bytes * b2)1318*8ccd4a63SDavid du Colombier catbytes(Bytes* b1, Bytes* b2)
1319*8ccd4a63SDavid du Colombier {
1320*8ccd4a63SDavid du Colombier 	Bytes* ans;
1321*8ccd4a63SDavid du Colombier 	int n;
1322*8ccd4a63SDavid du Colombier 
1323*8ccd4a63SDavid du Colombier 	if(b1 == nil) {
1324*8ccd4a63SDavid du Colombier 		if(b2 == nil)
1325*8ccd4a63SDavid du Colombier 			ans = newbytes(0);
1326*8ccd4a63SDavid du Colombier 		else
1327*8ccd4a63SDavid du Colombier 			ans = makebytes(b2->data, b2->len);
1328*8ccd4a63SDavid du Colombier 	}
1329*8ccd4a63SDavid du Colombier 	else if(b2 == nil) {
1330*8ccd4a63SDavid du Colombier 		ans = makebytes(b1->data, b1->len);
1331*8ccd4a63SDavid du Colombier 	}
1332*8ccd4a63SDavid du Colombier 	else {
1333*8ccd4a63SDavid du Colombier 		n = b1->len + b2->len;
1334*8ccd4a63SDavid du Colombier 		ans = newbytes(n);
1335*8ccd4a63SDavid du Colombier 		ans->len = n;
1336*8ccd4a63SDavid du Colombier 		memmove(ans->data, b1->data, b1->len);
1337*8ccd4a63SDavid du Colombier 		memmove(ans->data+b1->len, b2->data, b2->len);
1338*8ccd4a63SDavid du Colombier 	}
1339*8ccd4a63SDavid du Colombier 	return ans;
1340*8ccd4a63SDavid du Colombier }
1341*8ccd4a63SDavid du Colombier 
1342*8ccd4a63SDavid du Colombier /* len is number of ints */
1343*8ccd4a63SDavid du Colombier static Ints*
newints(int len)1344*8ccd4a63SDavid du Colombier newints(int len)
1345*8ccd4a63SDavid du Colombier {
1346*8ccd4a63SDavid du Colombier 	Ints* ans;
1347*8ccd4a63SDavid du Colombier 
1348*8ccd4a63SDavid du Colombier 	ans = (Ints*)emalloc(OFFSETOF(data[0], Ints) + len*sizeof(int));
1349*8ccd4a63SDavid du Colombier 	ans->len = len;
1350*8ccd4a63SDavid du Colombier 	return ans;
1351*8ccd4a63SDavid du Colombier }
1352*8ccd4a63SDavid du Colombier 
1353*8ccd4a63SDavid du Colombier static Ints*
makeints(int * buf,int len)1354*8ccd4a63SDavid du Colombier makeints(int* buf, int len)
1355*8ccd4a63SDavid du Colombier {
1356*8ccd4a63SDavid du Colombier 	Ints* ans;
1357*8ccd4a63SDavid du Colombier 
1358*8ccd4a63SDavid du Colombier 	ans = newints(len);
1359*8ccd4a63SDavid du Colombier 	if(len > 0)
1360*8ccd4a63SDavid du Colombier 		memmove(ans->data, buf, len*sizeof(int));
1361*8ccd4a63SDavid du Colombier 	return ans;
1362*8ccd4a63SDavid du Colombier }
1363*8ccd4a63SDavid du Colombier 
1364*8ccd4a63SDavid du Colombier static void
freeints(Ints * b)1365*8ccd4a63SDavid du Colombier freeints(Ints* b)
1366*8ccd4a63SDavid du Colombier {
1367*8ccd4a63SDavid du Colombier 	if(b != nil)
1368*8ccd4a63SDavid du Colombier 		free(b);
1369*8ccd4a63SDavid du Colombier }
1370*8ccd4a63SDavid du Colombier 
1371*8ccd4a63SDavid du Colombier /* len is number of bytes */
1372*8ccd4a63SDavid du Colombier static Bits*
newbits(int len)1373*8ccd4a63SDavid du Colombier newbits(int len)
1374*8ccd4a63SDavid du Colombier {
1375*8ccd4a63SDavid du Colombier 	Bits* ans;
1376*8ccd4a63SDavid du Colombier 
1377*8ccd4a63SDavid du Colombier 	ans = (Bits*)emalloc(OFFSETOF(data[0], Bits) + len);
1378*8ccd4a63SDavid du Colombier 	ans->len = len;
1379*8ccd4a63SDavid du Colombier 	ans->unusedbits = 0;
1380*8ccd4a63SDavid du Colombier 	return ans;
1381*8ccd4a63SDavid du Colombier }
1382*8ccd4a63SDavid du Colombier 
1383*8ccd4a63SDavid du Colombier static Bits*
makebits(uchar * buf,int len,int unusedbits)1384*8ccd4a63SDavid du Colombier makebits(uchar* buf, int len, int unusedbits)
1385*8ccd4a63SDavid du Colombier {
1386*8ccd4a63SDavid du Colombier 	Bits* ans;
1387*8ccd4a63SDavid du Colombier 
1388*8ccd4a63SDavid du Colombier 	ans = newbits(len);
1389*8ccd4a63SDavid du Colombier 	memmove(ans->data, buf, len);
1390*8ccd4a63SDavid du Colombier 	ans->unusedbits = unusedbits;
1391*8ccd4a63SDavid du Colombier 	return ans;
1392*8ccd4a63SDavid du Colombier }
1393*8ccd4a63SDavid du Colombier 
1394*8ccd4a63SDavid du Colombier static void
freebits(Bits * b)1395*8ccd4a63SDavid du Colombier freebits(Bits* b)
1396*8ccd4a63SDavid du Colombier {
1397*8ccd4a63SDavid du Colombier 	if(b != nil)
1398*8ccd4a63SDavid du Colombier 		free(b);
1399*8ccd4a63SDavid du Colombier }
1400*8ccd4a63SDavid du Colombier 
1401*8ccd4a63SDavid du Colombier static Elist*
mkel(Elem e,Elist * tail)1402*8ccd4a63SDavid du Colombier mkel(Elem e, Elist* tail)
1403*8ccd4a63SDavid du Colombier {
1404*8ccd4a63SDavid du Colombier 	Elist* el;
1405*8ccd4a63SDavid du Colombier 
1406*8ccd4a63SDavid du Colombier 	el = (Elist*)emalloc(sizeof(Elist));
1407*8ccd4a63SDavid du Colombier 	el->hd = e;
1408*8ccd4a63SDavid du Colombier 	el->tl = tail;
1409*8ccd4a63SDavid du Colombier 	return el;
1410*8ccd4a63SDavid du Colombier }
1411*8ccd4a63SDavid du Colombier 
1412*8ccd4a63SDavid du Colombier static int
elistlen(Elist * el)1413*8ccd4a63SDavid du Colombier elistlen(Elist* el)
1414*8ccd4a63SDavid du Colombier {
1415*8ccd4a63SDavid du Colombier 	int ans = 0;
1416*8ccd4a63SDavid du Colombier 	while(el != nil) {
1417*8ccd4a63SDavid du Colombier 		ans++;
1418*8ccd4a63SDavid du Colombier 		el = el->tl;
1419*8ccd4a63SDavid du Colombier 	}
1420*8ccd4a63SDavid du Colombier 	return ans;
1421*8ccd4a63SDavid du Colombier }
1422*8ccd4a63SDavid du Colombier 
1423*8ccd4a63SDavid du Colombier /* Frees elist, but not fields inside values of constituent elems */
1424*8ccd4a63SDavid du Colombier static void
freeelist(Elist * el)1425*8ccd4a63SDavid du Colombier freeelist(Elist* el)
1426*8ccd4a63SDavid du Colombier {
1427*8ccd4a63SDavid du Colombier 	Elist* next;
1428*8ccd4a63SDavid du Colombier 
1429*8ccd4a63SDavid du Colombier 	while(el != nil) {
1430*8ccd4a63SDavid du Colombier 		next = el->tl;
1431*8ccd4a63SDavid du Colombier 		free(el);
1432*8ccd4a63SDavid du Colombier 		el = next;
1433*8ccd4a63SDavid du Colombier 	}
1434*8ccd4a63SDavid du Colombier }
1435*8ccd4a63SDavid du Colombier 
1436*8ccd4a63SDavid du Colombier /* free any allocated structures inside v (recursively freeing Elists) */
1437*8ccd4a63SDavid du Colombier static void
freevalfields(Value * v)1438*8ccd4a63SDavid du Colombier freevalfields(Value* v)
1439*8ccd4a63SDavid du Colombier {
1440*8ccd4a63SDavid du Colombier 	Elist* el;
1441*8ccd4a63SDavid du Colombier 	Elist* l;
1442*8ccd4a63SDavid du Colombier 	if(v == nil)
1443*8ccd4a63SDavid du Colombier 		return;
1444*8ccd4a63SDavid du Colombier 	switch(v->tag) {
1445*8ccd4a63SDavid du Colombier  	case VOctets:
1446*8ccd4a63SDavid du Colombier 		freebytes(v->u.octetsval);
1447*8ccd4a63SDavid du Colombier 		break;
1448*8ccd4a63SDavid du Colombier 	case VBigInt:
1449*8ccd4a63SDavid du Colombier 		freebytes(v->u.bigintval);
1450*8ccd4a63SDavid du Colombier 		break;
1451*8ccd4a63SDavid du Colombier 	case VReal:
1452*8ccd4a63SDavid du Colombier 		freebytes(v->u.realval);
1453*8ccd4a63SDavid du Colombier 		break;
1454*8ccd4a63SDavid du Colombier 	case VOther:
1455*8ccd4a63SDavid du Colombier 		freebytes(v->u.otherval);
1456*8ccd4a63SDavid du Colombier 		break;
1457*8ccd4a63SDavid du Colombier 	case VBitString:
1458*8ccd4a63SDavid du Colombier 		freebits(v->u.bitstringval);
1459*8ccd4a63SDavid du Colombier 		break;
1460*8ccd4a63SDavid du Colombier 	case VObjId:
1461*8ccd4a63SDavid du Colombier 		freeints(v->u.objidval);
1462*8ccd4a63SDavid du Colombier 		break;
1463*8ccd4a63SDavid du Colombier 	case VString:
1464*8ccd4a63SDavid du Colombier 		if (v->u.stringval)
1465*8ccd4a63SDavid du Colombier 			free(v->u.stringval);
1466*8ccd4a63SDavid du Colombier 		break;
1467*8ccd4a63SDavid du Colombier 	case VSeq:
1468*8ccd4a63SDavid du Colombier 		el = v->u.seqval;
1469*8ccd4a63SDavid du Colombier 		for(l = el; l != nil; l = l->tl)
1470*8ccd4a63SDavid du Colombier 			freevalfields(&l->hd.val);
1471*8ccd4a63SDavid du Colombier 		if (el)
1472*8ccd4a63SDavid du Colombier 			freeelist(el);
1473*8ccd4a63SDavid du Colombier 		break;
1474*8ccd4a63SDavid du Colombier 	case VSet:
1475*8ccd4a63SDavid du Colombier 		el = v->u.setval;
1476*8ccd4a63SDavid du Colombier 		for(l = el; l != nil; l = l->tl)
1477*8ccd4a63SDavid du Colombier 			freevalfields(&l->hd.val);
1478*8ccd4a63SDavid du Colombier 		if (el)
1479*8ccd4a63SDavid du Colombier 			freeelist(el);
1480*8ccd4a63SDavid du Colombier 		break;
1481*8ccd4a63SDavid du Colombier 	}
1482*8ccd4a63SDavid du Colombier }
1483*8ccd4a63SDavid du Colombier 
1484*8ccd4a63SDavid du Colombier /* end of general ASN1 functions */
1485*8ccd4a63SDavid du Colombier 
1486*8ccd4a63SDavid du Colombier 
1487*8ccd4a63SDavid du Colombier 
1488*8ccd4a63SDavid du Colombier 
1489*8ccd4a63SDavid du Colombier 
1490*8ccd4a63SDavid du Colombier /*=============================================================*/
1491*8ccd4a63SDavid du Colombier /*
1492*8ccd4a63SDavid du Colombier  * Decode and parse an X.509 Certificate, defined by this ASN1:
1493*8ccd4a63SDavid du Colombier  *	Certificate ::= SEQUENCE {
1494*8ccd4a63SDavid du Colombier  *		certificateInfo CertificateInfo,
1495*8ccd4a63SDavid du Colombier  *		signatureAlgorithm AlgorithmIdentifier,
1496*8ccd4a63SDavid du Colombier  *		signature BIT STRING }
1497*8ccd4a63SDavid du Colombier  *
1498*8ccd4a63SDavid du Colombier  *	CertificateInfo ::= SEQUENCE {
1499*8ccd4a63SDavid du Colombier  *		version [0] INTEGER DEFAULT v1 (0),
1500*8ccd4a63SDavid du Colombier  *		serialNumber INTEGER,
1501*8ccd4a63SDavid du Colombier  *		signature AlgorithmIdentifier,
1502*8ccd4a63SDavid du Colombier  *		issuer Name,
1503*8ccd4a63SDavid du Colombier  *		validity Validity,
1504*8ccd4a63SDavid du Colombier  *		subject Name,
1505*8ccd4a63SDavid du Colombier  *		subjectPublicKeyInfo SubjectPublicKeyInfo }
1506*8ccd4a63SDavid du Colombier  *	(version v2 has two more fields, optional unique identifiers for
1507*8ccd4a63SDavid du Colombier  *  issuer and subject; since we ignore these anyway, we won't parse them)
1508*8ccd4a63SDavid du Colombier  *
1509*8ccd4a63SDavid du Colombier  *	Validity ::= SEQUENCE {
1510*8ccd4a63SDavid du Colombier  *		notBefore UTCTime,
1511*8ccd4a63SDavid du Colombier  *		notAfter UTCTime }
1512*8ccd4a63SDavid du Colombier  *
1513*8ccd4a63SDavid du Colombier  *	SubjectPublicKeyInfo ::= SEQUENCE {
1514*8ccd4a63SDavid du Colombier  *		algorithm AlgorithmIdentifier,
1515*8ccd4a63SDavid du Colombier  *		subjectPublicKey BIT STRING }
1516*8ccd4a63SDavid du Colombier  *
1517*8ccd4a63SDavid du Colombier  *	AlgorithmIdentifier ::= SEQUENCE {
1518*8ccd4a63SDavid du Colombier  *		algorithm OBJECT IDENTIFER,
1519*8ccd4a63SDavid du Colombier  *		parameters ANY DEFINED BY ALGORITHM OPTIONAL }
1520*8ccd4a63SDavid du Colombier  *
1521*8ccd4a63SDavid du Colombier  *	Name ::= SEQUENCE OF RelativeDistinguishedName
1522*8ccd4a63SDavid du Colombier  *
1523*8ccd4a63SDavid du Colombier  *	RelativeDistinguishedName ::= SETOF SIZE(1..MAX) OF AttributeTypeAndValue
1524*8ccd4a63SDavid du Colombier  *
1525*8ccd4a63SDavid du Colombier  *	AttributeTypeAndValue ::= SEQUENCE {
1526*8ccd4a63SDavid du Colombier  *		type OBJECT IDENTIFER,
1527*8ccd4a63SDavid du Colombier  *		value DirectoryString }
1528*8ccd4a63SDavid du Colombier  *	(selected attributes have these Object Ids:
1529*8ccd4a63SDavid du Colombier  *		commonName {2 5 4 3}
1530*8ccd4a63SDavid du Colombier  *		countryName {2 5 4 6}
1531*8ccd4a63SDavid du Colombier  *		localityName {2 5 4 7}
1532*8ccd4a63SDavid du Colombier  *		stateOrProvinceName {2 5 4 8}
1533*8ccd4a63SDavid du Colombier  *		organizationName {2 5 4 10}
1534*8ccd4a63SDavid du Colombier  *		organizationalUnitName {2 5 4 11}
1535*8ccd4a63SDavid du Colombier  *	)
1536*8ccd4a63SDavid du Colombier  *
1537*8ccd4a63SDavid du Colombier  *	DirectoryString ::= CHOICE {
1538*8ccd4a63SDavid du Colombier  *		teletexString TeletexString,
1539*8ccd4a63SDavid du Colombier  *		printableString PrintableString,
1540*8ccd4a63SDavid du Colombier  *		universalString UniversalString }
1541*8ccd4a63SDavid du Colombier  *
1542*8ccd4a63SDavid du Colombier  *  See rfc1423, rfc2437 for AlgorithmIdentifier, subjectPublicKeyInfo, signature.
1543*8ccd4a63SDavid du Colombier  *
1544*8ccd4a63SDavid du Colombier  *  Not yet implemented:
1545*8ccd4a63SDavid du Colombier  *   CertificateRevocationList ::= SIGNED SEQUENCE{
1546*8ccd4a63SDavid du Colombier  *           signature       AlgorithmIdentifier,
1547*8ccd4a63SDavid du Colombier  *           issuer          Name,
1548*8ccd4a63SDavid du Colombier  *           lastUpdate      UTCTime,
1549*8ccd4a63SDavid du Colombier  *           nextUpdate      UTCTime,
1550*8ccd4a63SDavid du Colombier  *           revokedCertificates
1551*8ccd4a63SDavid du Colombier  *                           SEQUENCE OF CRLEntry OPTIONAL}
1552*8ccd4a63SDavid du Colombier  *   CRLEntry ::= SEQUENCE{
1553*8ccd4a63SDavid du Colombier  *           userCertificate SerialNumber,
1554*8ccd4a63SDavid du Colombier  *           revocationDate UTCTime}
1555*8ccd4a63SDavid du Colombier  */
1556*8ccd4a63SDavid du Colombier 
1557*8ccd4a63SDavid du Colombier typedef struct CertX509 {
1558*8ccd4a63SDavid du Colombier 	int	serial;
1559*8ccd4a63SDavid du Colombier 	char*	issuer;
1560*8ccd4a63SDavid du Colombier 	char*	validity_start;
1561*8ccd4a63SDavid du Colombier 	char*	validity_end;
1562*8ccd4a63SDavid du Colombier 	char*	subject;
1563*8ccd4a63SDavid du Colombier 	int	publickey_alg;
1564*8ccd4a63SDavid du Colombier 	Bytes*	publickey;
1565*8ccd4a63SDavid du Colombier 	int	signature_alg;
1566*8ccd4a63SDavid du Colombier 	Bytes*	signature;
1567*8ccd4a63SDavid du Colombier } CertX509;
1568*8ccd4a63SDavid du Colombier 
1569*8ccd4a63SDavid du Colombier /* Algorithm object-ids */
1570*8ccd4a63SDavid du Colombier enum {
1571*8ccd4a63SDavid du Colombier 	ALG_rsaEncryption,
1572*8ccd4a63SDavid du Colombier 	ALG_md2WithRSAEncryption,
1573*8ccd4a63SDavid du Colombier 	ALG_md4WithRSAEncryption,
1574*8ccd4a63SDavid du Colombier 	ALG_md5WithRSAEncryption,
1575*8ccd4a63SDavid du Colombier 	ALG_sha1WithRSAEncryption,
1576*8ccd4a63SDavid du Colombier 	ALG_md5,
1577*8ccd4a63SDavid du Colombier 	NUMALGS
1578*8ccd4a63SDavid du Colombier };
1579*8ccd4a63SDavid du Colombier typedef struct Ints7 {
1580*8ccd4a63SDavid du Colombier 	int		len;
1581*8ccd4a63SDavid du Colombier 	int		data[7];
1582*8ccd4a63SDavid du Colombier } Ints7;
1583*8ccd4a63SDavid du Colombier static Ints7 oid_rsaEncryption = {7, 1, 2, 840, 113549, 1, 1, 1 };
1584*8ccd4a63SDavid du Colombier static Ints7 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 };
1585*8ccd4a63SDavid du Colombier static Ints7 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 };
1586*8ccd4a63SDavid du Colombier static Ints7 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 };
1587*8ccd4a63SDavid du Colombier static Ints7 oid_sha1WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 5 };
1588*8ccd4a63SDavid du Colombier static Ints7 oid_md5 ={6, 1, 2, 840, 113549, 2, 5, 0 };
1589*8ccd4a63SDavid du Colombier static Ints *alg_oid_tab[NUMALGS+1] = {
1590*8ccd4a63SDavid du Colombier 	(Ints*)&oid_rsaEncryption,
1591*8ccd4a63SDavid du Colombier 	(Ints*)&oid_md2WithRSAEncryption,
1592*8ccd4a63SDavid du Colombier 	(Ints*)&oid_md4WithRSAEncryption,
1593*8ccd4a63SDavid du Colombier 	(Ints*)&oid_md5WithRSAEncryption,
1594*8ccd4a63SDavid du Colombier 	(Ints*)&oid_sha1WithRSAEncryption,
1595*8ccd4a63SDavid du Colombier 	(Ints*)&oid_md5,
1596*8ccd4a63SDavid du Colombier 	nil
1597*8ccd4a63SDavid du Colombier };
1598*8ccd4a63SDavid du Colombier static DigestFun digestalg[NUMALGS+1] = { md5, md5, md5, md5, sha1, md5, nil };
1599*8ccd4a63SDavid du Colombier 
1600*8ccd4a63SDavid du Colombier static void
freecert(CertX509 * c)1601*8ccd4a63SDavid du Colombier freecert(CertX509* c)
1602*8ccd4a63SDavid du Colombier {
1603*8ccd4a63SDavid du Colombier 	if (!c) return;
1604*8ccd4a63SDavid du Colombier 	if(c->issuer != nil)
1605*8ccd4a63SDavid du Colombier 		free(c->issuer);
1606*8ccd4a63SDavid du Colombier 	if(c->validity_start != nil)
1607*8ccd4a63SDavid du Colombier 		free(c->validity_start);
1608*8ccd4a63SDavid du Colombier 	if(c->validity_end != nil)
1609*8ccd4a63SDavid du Colombier 		free(c->validity_end);
1610*8ccd4a63SDavid du Colombier 	if(c->subject != nil)
1611*8ccd4a63SDavid du Colombier 		free(c->subject);
1612*8ccd4a63SDavid du Colombier 	freebytes(c->publickey);
1613*8ccd4a63SDavid du Colombier 	freebytes(c->signature);
1614*8ccd4a63SDavid du Colombier }
1615*8ccd4a63SDavid du Colombier 
1616*8ccd4a63SDavid du Colombier /*
1617*8ccd4a63SDavid du Colombier  * Parse the Name ASN1 type.
1618*8ccd4a63SDavid du Colombier  * The sequence of RelativeDistinguishedName's gives a sort of pathname,
1619*8ccd4a63SDavid du Colombier  * from most general to most specific.  Each element of the path can be
1620*8ccd4a63SDavid du Colombier  * one or more (but usually just one) attribute-value pair, such as
1621*8ccd4a63SDavid du Colombier  * countryName="US".
1622*8ccd4a63SDavid du Colombier  * We'll just form a "postal-style" address string by concatenating the elements
1623*8ccd4a63SDavid du Colombier  * from most specific to least specific, separated by commas.
1624*8ccd4a63SDavid du Colombier  * Return name-as-string (which must be freed by caller).
1625*8ccd4a63SDavid du Colombier  */
1626*8ccd4a63SDavid du Colombier static char*
parse_name(Elem * e)1627*8ccd4a63SDavid du Colombier parse_name(Elem* e)
1628*8ccd4a63SDavid du Colombier {
1629*8ccd4a63SDavid du Colombier 	Elist* el;
1630*8ccd4a63SDavid du Colombier 	Elem* es;
1631*8ccd4a63SDavid du Colombier 	Elist* esetl;
1632*8ccd4a63SDavid du Colombier 	Elem* eat;
1633*8ccd4a63SDavid du Colombier 	Elist* eatl;
1634*8ccd4a63SDavid du Colombier 	char* s;
1635*8ccd4a63SDavid du Colombier 	enum { MAXPARTS = 100 };
1636*8ccd4a63SDavid du Colombier 	char* parts[MAXPARTS];
1637*8ccd4a63SDavid du Colombier 	int i;
1638*8ccd4a63SDavid du Colombier 	int plen;
1639*8ccd4a63SDavid du Colombier 	char* ans = nil;
1640*8ccd4a63SDavid du Colombier 
1641*8ccd4a63SDavid du Colombier 	if(!is_seq(e, &el))
1642*8ccd4a63SDavid du Colombier 		goto errret;
1643*8ccd4a63SDavid du Colombier 	i = 0;
1644*8ccd4a63SDavid du Colombier 	plen = 0;
1645*8ccd4a63SDavid du Colombier 	while(el != nil) {
1646*8ccd4a63SDavid du Colombier 		es = &el->hd;
1647*8ccd4a63SDavid du Colombier 		if(!is_set(es, &esetl))
1648*8ccd4a63SDavid du Colombier 			goto errret;
1649*8ccd4a63SDavid du Colombier 		while(esetl != nil) {
1650*8ccd4a63SDavid du Colombier 			eat = &esetl->hd;
1651*8ccd4a63SDavid du Colombier 			if(!is_seq(eat, &eatl) || elistlen(eatl) != 2)
1652*8ccd4a63SDavid du Colombier 				goto errret;
1653*8ccd4a63SDavid du Colombier 			if(!is_string(&eatl->tl->hd, &s) || i>=MAXPARTS)
1654*8ccd4a63SDavid du Colombier 				goto errret;
1655*8ccd4a63SDavid du Colombier 			parts[i++] = s;
1656*8ccd4a63SDavid du Colombier 			plen += strlen(s) + 2;		/* room for ", " after */
1657*8ccd4a63SDavid du Colombier 			esetl = esetl->tl;
1658*8ccd4a63SDavid du Colombier 		}
1659*8ccd4a63SDavid du Colombier 		el = el->tl;
1660*8ccd4a63SDavid du Colombier 	}
1661*8ccd4a63SDavid du Colombier 	if(i > 0) {
1662*8ccd4a63SDavid du Colombier 		ans = (char*)emalloc(plen);
1663*8ccd4a63SDavid du Colombier 		*ans = '\0';
1664*8ccd4a63SDavid du Colombier 		while(--i >= 0) {
1665*8ccd4a63SDavid du Colombier 			s = parts[i];
1666*8ccd4a63SDavid du Colombier 			strcat(ans, s);
1667*8ccd4a63SDavid du Colombier 			if(i > 0)
1668*8ccd4a63SDavid du Colombier 				strcat(ans, ", ");
1669*8ccd4a63SDavid du Colombier 		}
1670*8ccd4a63SDavid du Colombier 	}
1671*8ccd4a63SDavid du Colombier 
1672*8ccd4a63SDavid du Colombier errret:
1673*8ccd4a63SDavid du Colombier 	return ans;
1674*8ccd4a63SDavid du Colombier }
1675*8ccd4a63SDavid du Colombier 
1676*8ccd4a63SDavid du Colombier /*
1677*8ccd4a63SDavid du Colombier  * Parse an AlgorithmIdentifer ASN1 type.
1678*8ccd4a63SDavid du Colombier  * Look up the oid in oid_tab and return one of OID_rsaEncryption, etc..,
1679*8ccd4a63SDavid du Colombier  * or -1 if not found.
1680*8ccd4a63SDavid du Colombier  * For now, ignore parameters, since none of our algorithms need them.
1681*8ccd4a63SDavid du Colombier  */
1682*8ccd4a63SDavid du Colombier static int
parse_alg(Elem * e)1683*8ccd4a63SDavid du Colombier parse_alg(Elem* e)
1684*8ccd4a63SDavid du Colombier {
1685*8ccd4a63SDavid du Colombier 	Elist* el;
1686*8ccd4a63SDavid du Colombier 	Ints* oid;
1687*8ccd4a63SDavid du Colombier 
1688*8ccd4a63SDavid du Colombier 	if(!is_seq(e, &el) || el == nil || !is_oid(&el->hd, &oid))
1689*8ccd4a63SDavid du Colombier 		return -1;
1690*8ccd4a63SDavid du Colombier 	return oid_lookup(oid, alg_oid_tab);
1691*8ccd4a63SDavid du Colombier }
1692*8ccd4a63SDavid du Colombier 
1693*8ccd4a63SDavid du Colombier static CertX509*
decode_cert(Bytes * a)1694*8ccd4a63SDavid du Colombier decode_cert(Bytes* a)
1695*8ccd4a63SDavid du Colombier {
1696*8ccd4a63SDavid du Colombier 	int ok = 0;
1697*8ccd4a63SDavid du Colombier 	int n;
1698*8ccd4a63SDavid du Colombier 	CertX509* c = nil;
1699*8ccd4a63SDavid du Colombier 	Elem  ecert;
1700*8ccd4a63SDavid du Colombier 	Elem* ecertinfo;
1701*8ccd4a63SDavid du Colombier 	Elem* esigalg;
1702*8ccd4a63SDavid du Colombier 	Elem* esig;
1703*8ccd4a63SDavid du Colombier 	Elem* eserial;
1704*8ccd4a63SDavid du Colombier 	Elem* eissuer;
1705*8ccd4a63SDavid du Colombier 	Elem* evalidity;
1706*8ccd4a63SDavid du Colombier 	Elem* esubj;
1707*8ccd4a63SDavid du Colombier 	Elem* epubkey;
1708*8ccd4a63SDavid du Colombier 	Elist* el;
1709*8ccd4a63SDavid du Colombier 	Elist* elcert = nil;
1710*8ccd4a63SDavid du Colombier 	Elist* elcertinfo = nil;
1711*8ccd4a63SDavid du Colombier 	Elist* elvalidity = nil;
1712*8ccd4a63SDavid du Colombier 	Elist* elpubkey = nil;
1713*8ccd4a63SDavid du Colombier 	Bits* bits = nil;
1714*8ccd4a63SDavid du Colombier 	Bytes* b;
1715*8ccd4a63SDavid du Colombier 	Elem* e;
1716*8ccd4a63SDavid du Colombier 
1717*8ccd4a63SDavid du Colombier 	if(decode(a->data, a->len, &ecert) != ASN_OK)
1718*8ccd4a63SDavid du Colombier 		goto errret;
1719*8ccd4a63SDavid du Colombier 
1720*8ccd4a63SDavid du Colombier 	c = (CertX509*)emalloc(sizeof(CertX509));
1721*8ccd4a63SDavid du Colombier 	c->serial = -1;
1722*8ccd4a63SDavid du Colombier 	c->issuer = nil;
1723*8ccd4a63SDavid du Colombier 	c->validity_start = nil;
1724*8ccd4a63SDavid du Colombier 	c->validity_end = nil;
1725*8ccd4a63SDavid du Colombier 	c->subject = nil;
1726*8ccd4a63SDavid du Colombier 	c->publickey_alg = -1;
1727*8ccd4a63SDavid du Colombier 	c->publickey = nil;
1728*8ccd4a63SDavid du Colombier 	c->signature_alg = -1;
1729*8ccd4a63SDavid du Colombier 	c->signature = nil;
1730*8ccd4a63SDavid du Colombier 
1731*8ccd4a63SDavid du Colombier 	/* Certificate */
1732*8ccd4a63SDavid du Colombier  	if(!is_seq(&ecert, &elcert) || elistlen(elcert) !=3)
1733*8ccd4a63SDavid du Colombier 		goto errret;
1734*8ccd4a63SDavid du Colombier  	ecertinfo = &elcert->hd;
1735*8ccd4a63SDavid du Colombier  	el = elcert->tl;
1736*8ccd4a63SDavid du Colombier  	esigalg = &el->hd;
1737*8ccd4a63SDavid du Colombier 	c->signature_alg = parse_alg(esigalg);
1738*8ccd4a63SDavid du Colombier  	el = el->tl;
1739*8ccd4a63SDavid du Colombier  	esig = &el->hd;
1740*8ccd4a63SDavid du Colombier 
1741*8ccd4a63SDavid du Colombier 	/* Certificate Info */
1742*8ccd4a63SDavid du Colombier 	if(!is_seq(ecertinfo, &elcertinfo))
1743*8ccd4a63SDavid du Colombier 		goto errret;
1744*8ccd4a63SDavid du Colombier 	n = elistlen(elcertinfo);
1745*8ccd4a63SDavid du Colombier   	if(n < 6)
1746*8ccd4a63SDavid du Colombier 		goto errret;
1747*8ccd4a63SDavid du Colombier 	eserial =&elcertinfo->hd;
1748*8ccd4a63SDavid du Colombier  	el = elcertinfo->tl;
1749*8ccd4a63SDavid du Colombier  	/* check for optional version, marked by explicit context tag 0 */
1750*8ccd4a63SDavid du Colombier 	if(eserial->tag.class == Context && eserial->tag.num == 0) {
1751*8ccd4a63SDavid du Colombier  		eserial = &el->hd;
1752*8ccd4a63SDavid du Colombier  		if(n < 7)
1753*8ccd4a63SDavid du Colombier  			goto errret;
1754*8ccd4a63SDavid du Colombier  		el = el->tl;
1755*8ccd4a63SDavid du Colombier  	}
1756*8ccd4a63SDavid du Colombier 
1757*8ccd4a63SDavid du Colombier 	if(parse_alg(&el->hd) != c->signature_alg)
1758*8ccd4a63SDavid du Colombier 		goto errret;
1759*8ccd4a63SDavid du Colombier  	el = el->tl;
1760*8ccd4a63SDavid du Colombier  	eissuer = &el->hd;
1761*8ccd4a63SDavid du Colombier  	el = el->tl;
1762*8ccd4a63SDavid du Colombier  	evalidity = &el->hd;
1763*8ccd4a63SDavid du Colombier  	el = el->tl;
1764*8ccd4a63SDavid du Colombier  	esubj = &el->hd;
1765*8ccd4a63SDavid du Colombier  	el = el->tl;
1766*8ccd4a63SDavid du Colombier  	epubkey = &el->hd;
1767*8ccd4a63SDavid du Colombier  	if(!is_int(eserial, &c->serial)) {
1768*8ccd4a63SDavid du Colombier 		if(!is_bigint(eserial, &b))
1769*8ccd4a63SDavid du Colombier 			goto errret;
1770*8ccd4a63SDavid du Colombier 		c->serial = -1;	/* else we have to change cert struct */
1771*8ccd4a63SDavid du Colombier   	}
1772*8ccd4a63SDavid du Colombier 	c->issuer = parse_name(eissuer);
1773*8ccd4a63SDavid du Colombier 	if(c->issuer == nil)
1774*8ccd4a63SDavid du Colombier 		goto errret;
1775*8ccd4a63SDavid du Colombier 	/* Validity */
1776*8ccd4a63SDavid du Colombier   	if(!is_seq(evalidity, &elvalidity))
1777*8ccd4a63SDavid du Colombier 		goto errret;
1778*8ccd4a63SDavid du Colombier 	if(elistlen(elvalidity) != 2)
1779*8ccd4a63SDavid du Colombier 		goto errret;
1780*8ccd4a63SDavid du Colombier 	e = &elvalidity->hd;
1781*8ccd4a63SDavid du Colombier 	if(!is_time(e, &c->validity_start))
1782*8ccd4a63SDavid du Colombier 		goto errret;
1783*8ccd4a63SDavid du Colombier 	e->val.u.stringval = nil;	/* string ownership transfer */
1784*8ccd4a63SDavid du Colombier 	e = &elvalidity->tl->hd;
1785*8ccd4a63SDavid du Colombier  	if(!is_time(e, &c->validity_end))
1786*8ccd4a63SDavid du Colombier 		goto errret;
1787*8ccd4a63SDavid du Colombier 	e->val.u.stringval = nil;	/* string ownership transfer */
1788*8ccd4a63SDavid du Colombier 
1789*8ccd4a63SDavid du Colombier 	/* resume CertificateInfo */
1790*8ccd4a63SDavid du Colombier  	c->subject = parse_name(esubj);
1791*8ccd4a63SDavid du Colombier 	if(c->subject == nil)
1792*8ccd4a63SDavid du Colombier 		goto errret;
1793*8ccd4a63SDavid du Colombier 
1794*8ccd4a63SDavid du Colombier 	/* SubjectPublicKeyInfo */
1795*8ccd4a63SDavid du Colombier  	if(!is_seq(epubkey, &elpubkey))
1796*8ccd4a63SDavid du Colombier 		goto errret;
1797*8ccd4a63SDavid du Colombier 	if(elistlen(elpubkey) != 2)
1798*8ccd4a63SDavid du Colombier 		goto errret;
1799*8ccd4a63SDavid du Colombier 
1800*8ccd4a63SDavid du Colombier 	c->publickey_alg = parse_alg(&elpubkey->hd);
1801*8ccd4a63SDavid du Colombier 	if(c->publickey_alg < 0)
1802*8ccd4a63SDavid du Colombier 		goto errret;
1803*8ccd4a63SDavid du Colombier   	if(!is_bitstring(&elpubkey->tl->hd, &bits))
1804*8ccd4a63SDavid du Colombier 		goto errret;
1805*8ccd4a63SDavid du Colombier 	if(bits->unusedbits != 0)
1806*8ccd4a63SDavid du Colombier 		goto errret;
1807*8ccd4a63SDavid du Colombier  	c->publickey = makebytes(bits->data, bits->len);
1808*8ccd4a63SDavid du Colombier 
1809*8ccd4a63SDavid du Colombier 	/*resume Certificate */
1810*8ccd4a63SDavid du Colombier 	if(c->signature_alg < 0)
1811*8ccd4a63SDavid du Colombier 		goto errret;
1812*8ccd4a63SDavid du Colombier  	if(!is_bitstring(esig, &bits))
1813*8ccd4a63SDavid du Colombier 		goto errret;
1814*8ccd4a63SDavid du Colombier  	c->signature = makebytes(bits->data, bits->len);
1815*8ccd4a63SDavid du Colombier 	ok = 1;
1816*8ccd4a63SDavid du Colombier 
1817*8ccd4a63SDavid du Colombier errret:
1818*8ccd4a63SDavid du Colombier 	freevalfields(&ecert.val);	/* recurses through lists, too */
1819*8ccd4a63SDavid du Colombier 	if(!ok){
1820*8ccd4a63SDavid du Colombier 		freecert(c);
1821*8ccd4a63SDavid du Colombier 		c = nil;
1822*8ccd4a63SDavid du Colombier 	}
1823*8ccd4a63SDavid du Colombier 	return c;
1824*8ccd4a63SDavid du Colombier }
1825*8ccd4a63SDavid du Colombier 
1826*8ccd4a63SDavid du Colombier /*
1827*8ccd4a63SDavid du Colombier  *	RSAPublickKey :: SEQUENCE {
1828*8ccd4a63SDavid du Colombier  *		modulus INTEGER,
1829*8ccd4a63SDavid du Colombier  *		publicExponent INTEGER
1830*8ccd4a63SDavid du Colombier  *	}
1831*8ccd4a63SDavid du Colombier  */
1832*8ccd4a63SDavid du Colombier static RSApub*
decode_rsapubkey(Bytes * a)1833*8ccd4a63SDavid du Colombier decode_rsapubkey(Bytes* a)
1834*8ccd4a63SDavid du Colombier {
1835*8ccd4a63SDavid du Colombier 	Elem e;
1836*8ccd4a63SDavid du Colombier 	Elist *el;
1837*8ccd4a63SDavid du Colombier 	mpint *mp;
1838*8ccd4a63SDavid du Colombier 	RSApub* key;
1839*8ccd4a63SDavid du Colombier 
1840*8ccd4a63SDavid du Colombier 	key = rsapuballoc();
1841*8ccd4a63SDavid du Colombier 	if(decode(a->data, a->len, &e) != ASN_OK)
1842*8ccd4a63SDavid du Colombier 		goto errret;
1843*8ccd4a63SDavid du Colombier 	if(!is_seq(&e, &el) || elistlen(el) != 2)
1844*8ccd4a63SDavid du Colombier 		goto errret;
1845*8ccd4a63SDavid du Colombier 
1846*8ccd4a63SDavid du Colombier 	key->n = mp = asn1mpint(&el->hd);
1847*8ccd4a63SDavid du Colombier 	if(mp == nil)
1848*8ccd4a63SDavid du Colombier 		goto errret;
1849*8ccd4a63SDavid du Colombier 
1850*8ccd4a63SDavid du Colombier 	el = el->tl;
1851*8ccd4a63SDavid du Colombier 	key->ek = mp = asn1mpint(&el->hd);
1852*8ccd4a63SDavid du Colombier 	if(mp == nil)
1853*8ccd4a63SDavid du Colombier 		goto errret;
1854*8ccd4a63SDavid du Colombier 	return key;
1855*8ccd4a63SDavid du Colombier errret:
1856*8ccd4a63SDavid du Colombier 	rsapubfree(key);
1857*8ccd4a63SDavid du Colombier 	return nil;
1858*8ccd4a63SDavid du Colombier }
1859*8ccd4a63SDavid du Colombier 
1860*8ccd4a63SDavid du Colombier /*
1861*8ccd4a63SDavid du Colombier  *	RSAPrivateKey ::= SEQUENCE {
1862*8ccd4a63SDavid du Colombier  *		version Version,
1863*8ccd4a63SDavid du Colombier  *		modulus INTEGER, -- n
1864*8ccd4a63SDavid du Colombier  *		publicExponent INTEGER, -- e
1865*8ccd4a63SDavid du Colombier  *		privateExponent INTEGER, -- d
1866*8ccd4a63SDavid du Colombier  *		prime1 INTEGER, -- p
1867*8ccd4a63SDavid du Colombier  *		prime2 INTEGER, -- q
1868*8ccd4a63SDavid du Colombier  *		exponent1 INTEGER, -- d mod (p-1)
1869*8ccd4a63SDavid du Colombier  *		exponent2 INTEGER, -- d mod (q-1)
1870*8ccd4a63SDavid du Colombier  *		coefficient INTEGER -- (inverse of q) mod p }
1871*8ccd4a63SDavid du Colombier  */
1872*8ccd4a63SDavid du Colombier static RSApriv*
decode_rsaprivkey(Bytes * a)1873*8ccd4a63SDavid du Colombier decode_rsaprivkey(Bytes* a)
1874*8ccd4a63SDavid du Colombier {
1875*8ccd4a63SDavid du Colombier 	int version;
1876*8ccd4a63SDavid du Colombier 	Elem e;
1877*8ccd4a63SDavid du Colombier 	Elist *el;
1878*8ccd4a63SDavid du Colombier 	mpint *mp;
1879*8ccd4a63SDavid du Colombier 	RSApriv* key;
1880*8ccd4a63SDavid du Colombier 
1881*8ccd4a63SDavid du Colombier 	key = rsaprivalloc();
1882*8ccd4a63SDavid du Colombier 	if(decode(a->data, a->len, &e) != ASN_OK)
1883*8ccd4a63SDavid du Colombier 		goto errret;
1884*8ccd4a63SDavid du Colombier 	if(!is_seq(&e, &el) || elistlen(el) != 9)
1885*8ccd4a63SDavid du Colombier 		goto errret;
1886*8ccd4a63SDavid du Colombier 	if(!is_int(&el->hd, &version) || version != 0)
1887*8ccd4a63SDavid du Colombier 		goto errret;
1888*8ccd4a63SDavid du Colombier 
1889*8ccd4a63SDavid du Colombier 	el = el->tl;
1890*8ccd4a63SDavid du Colombier 	key->pub.n = mp = asn1mpint(&el->hd);
1891*8ccd4a63SDavid du Colombier 	if(mp == nil)
1892*8ccd4a63SDavid du Colombier 		goto errret;
1893*8ccd4a63SDavid du Colombier 
1894*8ccd4a63SDavid du Colombier 	el = el->tl;
1895*8ccd4a63SDavid du Colombier 	key->pub.ek = mp = asn1mpint(&el->hd);
1896*8ccd4a63SDavid du Colombier 	if(mp == nil)
1897*8ccd4a63SDavid du Colombier 		goto errret;
1898*8ccd4a63SDavid du Colombier 
1899*8ccd4a63SDavid du Colombier 	el = el->tl;
1900*8ccd4a63SDavid du Colombier 	key->dk = mp = asn1mpint(&el->hd);
1901*8ccd4a63SDavid du Colombier 	if(mp == nil)
1902*8ccd4a63SDavid du Colombier 		goto errret;
1903*8ccd4a63SDavid du Colombier 
1904*8ccd4a63SDavid du Colombier 	el = el->tl;
1905*8ccd4a63SDavid du Colombier 	key->q = mp = asn1mpint(&el->hd);
1906*8ccd4a63SDavid du Colombier 	if(mp == nil)
1907*8ccd4a63SDavid du Colombier 		goto errret;
1908*8ccd4a63SDavid du Colombier 
1909*8ccd4a63SDavid du Colombier 	el = el->tl;
1910*8ccd4a63SDavid du Colombier 	key->p = mp = asn1mpint(&el->hd);
1911*8ccd4a63SDavid du Colombier 	if(mp == nil)
1912*8ccd4a63SDavid du Colombier 		goto errret;
1913*8ccd4a63SDavid du Colombier 
1914*8ccd4a63SDavid du Colombier 	el = el->tl;
1915*8ccd4a63SDavid du Colombier 	key->kq = mp = asn1mpint(&el->hd);
1916*8ccd4a63SDavid du Colombier 	if(mp == nil)
1917*8ccd4a63SDavid du Colombier 		goto errret;
1918*8ccd4a63SDavid du Colombier 
1919*8ccd4a63SDavid du Colombier 	el = el->tl;
1920*8ccd4a63SDavid du Colombier 	key->kp = mp = asn1mpint(&el->hd);
1921*8ccd4a63SDavid du Colombier 	if(mp == nil)
1922*8ccd4a63SDavid du Colombier 		goto errret;
1923*8ccd4a63SDavid du Colombier 
1924*8ccd4a63SDavid du Colombier 	el = el->tl;
1925*8ccd4a63SDavid du Colombier 	key->c2 = mp = asn1mpint(&el->hd);
1926*8ccd4a63SDavid du Colombier 	if(mp == nil)
1927*8ccd4a63SDavid du Colombier 		goto errret;
1928*8ccd4a63SDavid du Colombier 
1929*8ccd4a63SDavid du Colombier 	return key;
1930*8ccd4a63SDavid du Colombier errret:
1931*8ccd4a63SDavid du Colombier 	rsaprivfree(key);
1932*8ccd4a63SDavid du Colombier 	return nil;
1933*8ccd4a63SDavid du Colombier }
1934*8ccd4a63SDavid du Colombier 
1935*8ccd4a63SDavid du Colombier static mpint*
asn1mpint(Elem * e)1936*8ccd4a63SDavid du Colombier asn1mpint(Elem *e)
1937*8ccd4a63SDavid du Colombier {
1938*8ccd4a63SDavid du Colombier 	Bytes *b;
1939*8ccd4a63SDavid du Colombier 	mpint *mp;
1940*8ccd4a63SDavid du Colombier 	int v;
1941*8ccd4a63SDavid du Colombier 
1942*8ccd4a63SDavid du Colombier 	if(is_int(e, &v))
1943*8ccd4a63SDavid du Colombier 		return itomp(v, nil);
1944*8ccd4a63SDavid du Colombier 	if(is_bigint(e, &b)) {
1945*8ccd4a63SDavid du Colombier 		mp = betomp(b->data, b->len, nil);
1946*8ccd4a63SDavid du Colombier 		freebytes(b);
1947*8ccd4a63SDavid du Colombier 		return mp;
1948*8ccd4a63SDavid du Colombier 	}
1949*8ccd4a63SDavid du Colombier 	return nil;
1950*8ccd4a63SDavid du Colombier }
1951*8ccd4a63SDavid du Colombier 
1952*8ccd4a63SDavid du Colombier static mpint*
pkcs1pad(Bytes * b,mpint * modulus)1953*8ccd4a63SDavid du Colombier pkcs1pad(Bytes *b, mpint *modulus)
1954*8ccd4a63SDavid du Colombier {
1955*8ccd4a63SDavid du Colombier 	int n = (mpsignif(modulus)+7)/8;
1956*8ccd4a63SDavid du Colombier 	int pm1, i;
1957*8ccd4a63SDavid du Colombier 	uchar *p;
1958*8ccd4a63SDavid du Colombier 	mpint *mp;
1959*8ccd4a63SDavid du Colombier 
1960*8ccd4a63SDavid du Colombier 	pm1 = n - 1 - b->len;
1961*8ccd4a63SDavid du Colombier 	p = (uchar*)emalloc(n);
1962*8ccd4a63SDavid du Colombier 	p[0] = 0;
1963*8ccd4a63SDavid du Colombier 	p[1] = 1;
1964*8ccd4a63SDavid du Colombier 	for(i = 2; i < pm1; i++)
1965*8ccd4a63SDavid du Colombier 		p[i] = 0xFF;
1966*8ccd4a63SDavid du Colombier 	p[pm1] = 0;
1967*8ccd4a63SDavid du Colombier 	memcpy(&p[pm1+1], b->data, b->len);
1968*8ccd4a63SDavid du Colombier 	mp = betomp(p, n, nil);
1969*8ccd4a63SDavid du Colombier 	free(p);
1970*8ccd4a63SDavid du Colombier 	return mp;
1971*8ccd4a63SDavid du Colombier }
1972*8ccd4a63SDavid du Colombier 
1973*8ccd4a63SDavid du Colombier RSApriv*
asn1toRSApriv(uchar * kd,int kn)1974*8ccd4a63SDavid du Colombier asn1toRSApriv(uchar *kd, int kn)
1975*8ccd4a63SDavid du Colombier {
1976*8ccd4a63SDavid du Colombier 	Bytes *b;
1977*8ccd4a63SDavid du Colombier 	RSApriv *key;
1978*8ccd4a63SDavid du Colombier 
1979*8ccd4a63SDavid du Colombier 	b = makebytes(kd, kn);
1980*8ccd4a63SDavid du Colombier 	key = decode_rsaprivkey(b);
1981*8ccd4a63SDavid du Colombier 	freebytes(b);
1982*8ccd4a63SDavid du Colombier 	return key;
1983*8ccd4a63SDavid du Colombier }
1984*8ccd4a63SDavid du Colombier 
1985*8ccd4a63SDavid du Colombier /*
1986*8ccd4a63SDavid du Colombier  * digest(CertificateInfo)
1987*8ccd4a63SDavid du Colombier  * Our ASN.1 library doesn't return pointers into the original
1988*8ccd4a63SDavid du Colombier  * data array, so we need to do a little hand decoding.
1989*8ccd4a63SDavid du Colombier  */
1990*8ccd4a63SDavid du Colombier static void
digest_certinfo(Bytes * cert,DigestFun digestfun,uchar * digest)1991*8ccd4a63SDavid du Colombier digest_certinfo(Bytes *cert, DigestFun digestfun, uchar *digest)
1992*8ccd4a63SDavid du Colombier {
1993*8ccd4a63SDavid du Colombier 	uchar *info, *p, *pend;
1994*8ccd4a63SDavid du Colombier 	ulong infolen;
1995*8ccd4a63SDavid du Colombier 	int isconstr, length;
1996*8ccd4a63SDavid du Colombier 	Tag tag;
1997*8ccd4a63SDavid du Colombier 	Elem elem;
1998*8ccd4a63SDavid du Colombier 
1999*8ccd4a63SDavid du Colombier 	p = cert->data;
2000*8ccd4a63SDavid du Colombier 	pend = cert->data + cert->len;
2001*8ccd4a63SDavid du Colombier 	if(tag_decode(&p, pend, &tag, &isconstr) != ASN_OK ||
2002*8ccd4a63SDavid du Colombier 			tag.class != Universal || tag.num != SEQUENCE ||
2003*8ccd4a63SDavid du Colombier 			length_decode(&p, pend, &length) != ASN_OK ||
2004*8ccd4a63SDavid du Colombier 			p+length > pend)
2005*8ccd4a63SDavid du Colombier 		return;
2006*8ccd4a63SDavid du Colombier 	info = p;
2007*8ccd4a63SDavid du Colombier 	if(ber_decode(&p, pend, &elem) != ASN_OK || elem.tag.num != SEQUENCE)
2008*8ccd4a63SDavid du Colombier 		return;
2009*8ccd4a63SDavid du Colombier 	infolen = p - info;
2010*8ccd4a63SDavid du Colombier 	(*digestfun)(info, infolen, digest, nil);
2011*8ccd4a63SDavid du Colombier }
2012*8ccd4a63SDavid du Colombier 
2013*8ccd4a63SDavid du Colombier static char*
verify_signature(Bytes * signature,RSApub * pk,uchar * edigest,Elem ** psigalg)2014*8ccd4a63SDavid du Colombier verify_signature(Bytes* signature, RSApub *pk, uchar *edigest, Elem **psigalg)
2015*8ccd4a63SDavid du Colombier {
2016*8ccd4a63SDavid du Colombier 	Elem e;
2017*8ccd4a63SDavid du Colombier 	Elist *el;
2018*8ccd4a63SDavid du Colombier 	Bytes *digest;
2019*8ccd4a63SDavid du Colombier 	uchar *pkcs1buf, *buf;
2020*8ccd4a63SDavid du Colombier 	int buflen;
2021*8ccd4a63SDavid du Colombier 	mpint *pkcs1;
2022*8ccd4a63SDavid du Colombier 
2023*8ccd4a63SDavid du Colombier 	/* see 9.2.1 of rfc2437 */
2024*8ccd4a63SDavid du Colombier 	pkcs1 = betomp(signature->data, signature->len, nil);
2025*8ccd4a63SDavid du Colombier 	mpexp(pkcs1, pk->ek, pk->n, pkcs1);
2026*8ccd4a63SDavid du Colombier 	buflen = mptobe(pkcs1, nil, 0, &pkcs1buf);
2027*8ccd4a63SDavid du Colombier 	buf = pkcs1buf;
2028*8ccd4a63SDavid du Colombier 	if(buflen < 4 || buf[0] != 1)
2029*8ccd4a63SDavid du Colombier 		return "expected 1";
2030*8ccd4a63SDavid du Colombier 	buf++;
2031*8ccd4a63SDavid du Colombier 	while(buf[0] == 0xff)
2032*8ccd4a63SDavid du Colombier 		buf++;
2033*8ccd4a63SDavid du Colombier 	if(buf[0] != 0)
2034*8ccd4a63SDavid du Colombier 		return "expected 0";
2035*8ccd4a63SDavid du Colombier 	buf++;
2036*8ccd4a63SDavid du Colombier 	buflen -= buf-pkcs1buf;
2037*8ccd4a63SDavid du Colombier 	if(decode(buf, buflen, &e) != ASN_OK || !is_seq(&e, &el) || elistlen(el) != 2 ||
2038*8ccd4a63SDavid du Colombier 			!is_octetstring(&el->tl->hd, &digest))
2039*8ccd4a63SDavid du Colombier 		return "signature parse error";
2040*8ccd4a63SDavid du Colombier 	*psigalg = &el->hd;
2041*8ccd4a63SDavid du Colombier 	if(memcmp(digest->data, edigest, digest->len) == 0)
2042*8ccd4a63SDavid du Colombier 		return nil;
2043*8ccd4a63SDavid du Colombier 	return "digests did not match";
2044*8ccd4a63SDavid du Colombier }
2045*8ccd4a63SDavid du Colombier 
2046*8ccd4a63SDavid du Colombier RSApub*
X509toRSApub(uchar * cert,int ncert,char * name,int nname)2047*8ccd4a63SDavid du Colombier X509toRSApub(uchar *cert, int ncert, char *name, int nname)
2048*8ccd4a63SDavid du Colombier {
2049*8ccd4a63SDavid du Colombier 	char *e;
2050*8ccd4a63SDavid du Colombier 	Bytes *b;
2051*8ccd4a63SDavid du Colombier 	CertX509 *c;
2052*8ccd4a63SDavid du Colombier 	RSApub *pk;
2053*8ccd4a63SDavid du Colombier 
2054*8ccd4a63SDavid du Colombier 	b = makebytes(cert, ncert);
2055*8ccd4a63SDavid du Colombier 	c = decode_cert(b);
2056*8ccd4a63SDavid du Colombier 	freebytes(b);
2057*8ccd4a63SDavid du Colombier 	if(c == nil)
2058*8ccd4a63SDavid du Colombier 		return nil;
2059*8ccd4a63SDavid du Colombier 	if(name != nil && c->subject != nil){
2060*8ccd4a63SDavid du Colombier 		e = strchr(c->subject, ',');
2061*8ccd4a63SDavid du Colombier 		if(e != nil)
2062*8ccd4a63SDavid du Colombier 			*e = 0;  // take just CN part of Distinguished Name
2063*8ccd4a63SDavid du Colombier 		strncpy(name, c->subject, nname);
2064*8ccd4a63SDavid du Colombier 	}
2065*8ccd4a63SDavid du Colombier 	pk = decode_rsapubkey(c->publickey);
2066*8ccd4a63SDavid du Colombier 	freecert(c);
2067*8ccd4a63SDavid du Colombier 	return pk;
2068*8ccd4a63SDavid du Colombier }
2069*8ccd4a63SDavid du Colombier 
2070*8ccd4a63SDavid du Colombier char*
X509verify(uchar * cert,int ncert,RSApub * pk)2071*8ccd4a63SDavid du Colombier X509verify(uchar *cert, int ncert, RSApub *pk)
2072*8ccd4a63SDavid du Colombier {
2073*8ccd4a63SDavid du Colombier 	char *e;
2074*8ccd4a63SDavid du Colombier 	Bytes *b;
2075*8ccd4a63SDavid du Colombier 	CertX509 *c;
2076*8ccd4a63SDavid du Colombier 	uchar digest[SHA1dlen];
2077*8ccd4a63SDavid du Colombier 	Elem *sigalg;
2078*8ccd4a63SDavid du Colombier 
2079*8ccd4a63SDavid du Colombier 	b = makebytes(cert, ncert);
2080*8ccd4a63SDavid du Colombier 	c = decode_cert(b);
2081*8ccd4a63SDavid du Colombier 	if(c != nil)
2082*8ccd4a63SDavid du Colombier 		digest_certinfo(b, digestalg[c->signature_alg], digest);
2083*8ccd4a63SDavid du Colombier 	freebytes(b);
2084*8ccd4a63SDavid du Colombier 	if(c == nil)
2085*8ccd4a63SDavid du Colombier 		return "cannot decode cert";
2086*8ccd4a63SDavid du Colombier 	e = verify_signature(c->signature, pk, digest, &sigalg);
2087*8ccd4a63SDavid du Colombier 	freecert(c);
2088*8ccd4a63SDavid du Colombier 	return e;
2089*8ccd4a63SDavid du Colombier }
2090*8ccd4a63SDavid du Colombier 
2091*8ccd4a63SDavid du Colombier /* ------- Elem constructors ---------- */
2092*8ccd4a63SDavid du Colombier static Elem
Null(void)2093*8ccd4a63SDavid du Colombier Null(void)
2094*8ccd4a63SDavid du Colombier {
2095*8ccd4a63SDavid du Colombier 	Elem e;
2096*8ccd4a63SDavid du Colombier 
2097*8ccd4a63SDavid du Colombier 	e.tag.class = Universal;
2098*8ccd4a63SDavid du Colombier 	e.tag.num = NULLTAG;
2099*8ccd4a63SDavid du Colombier 	e.val.tag = VNull;
2100*8ccd4a63SDavid du Colombier 	return e;
2101*8ccd4a63SDavid du Colombier }
2102*8ccd4a63SDavid du Colombier 
2103*8ccd4a63SDavid du Colombier static Elem
mkint(int j)2104*8ccd4a63SDavid du Colombier mkint(int j)
2105*8ccd4a63SDavid du Colombier {
2106*8ccd4a63SDavid du Colombier 	Elem e;
2107*8ccd4a63SDavid du Colombier 
2108*8ccd4a63SDavid du Colombier 	e.tag.class = Universal;
2109*8ccd4a63SDavid du Colombier 	e.tag.num = INTEGER;
2110*8ccd4a63SDavid du Colombier 	e.val.tag = VInt;
2111*8ccd4a63SDavid du Colombier 	e.val.u.intval = j;
2112*8ccd4a63SDavid du Colombier 	return e;
2113*8ccd4a63SDavid du Colombier }
2114*8ccd4a63SDavid du Colombier 
2115*8ccd4a63SDavid du Colombier static Elem
mkbigint(mpint * p)2116*8ccd4a63SDavid du Colombier mkbigint(mpint *p)
2117*8ccd4a63SDavid du Colombier {
2118*8ccd4a63SDavid du Colombier 	Elem e;
2119*8ccd4a63SDavid du Colombier 	uchar *buf;
2120*8ccd4a63SDavid du Colombier 	int buflen;
2121*8ccd4a63SDavid du Colombier 
2122*8ccd4a63SDavid du Colombier 	e.tag.class = Universal;
2123*8ccd4a63SDavid du Colombier 	e.tag.num = INTEGER;
2124*8ccd4a63SDavid du Colombier 	e.val.tag = VBigInt;
2125*8ccd4a63SDavid du Colombier 	buflen = mptobe(p, nil, 0, &buf);
2126*8ccd4a63SDavid du Colombier 	e.val.u.bigintval = makebytes(buf, buflen);
2127*8ccd4a63SDavid du Colombier 	free(buf);
2128*8ccd4a63SDavid du Colombier 	return e;
2129*8ccd4a63SDavid du Colombier }
2130*8ccd4a63SDavid du Colombier 
2131*8ccd4a63SDavid du Colombier static Elem
mkstring(char * s)2132*8ccd4a63SDavid du Colombier mkstring(char *s)
2133*8ccd4a63SDavid du Colombier {
2134*8ccd4a63SDavid du Colombier 	Elem e;
2135*8ccd4a63SDavid du Colombier 
2136*8ccd4a63SDavid du Colombier 	e.tag.class = Universal;
2137*8ccd4a63SDavid du Colombier 	e.tag.num = IA5String;
2138*8ccd4a63SDavid du Colombier 	e.val.tag = VString;
2139*8ccd4a63SDavid du Colombier 	e.val.u.stringval = estrdup(s);
2140*8ccd4a63SDavid du Colombier 	return e;
2141*8ccd4a63SDavid du Colombier }
2142*8ccd4a63SDavid du Colombier 
2143*8ccd4a63SDavid du Colombier static Elem
mkoctet(uchar * buf,int buflen)2144*8ccd4a63SDavid du Colombier mkoctet(uchar *buf, int buflen)
2145*8ccd4a63SDavid du Colombier {
2146*8ccd4a63SDavid du Colombier 	Elem e;
2147*8ccd4a63SDavid du Colombier 
2148*8ccd4a63SDavid du Colombier 	e.tag.class = Universal;
2149*8ccd4a63SDavid du Colombier 	e.tag.num = OCTET_STRING;
2150*8ccd4a63SDavid du Colombier 	e.val.tag = VOctets;
2151*8ccd4a63SDavid du Colombier 	e.val.u.octetsval = makebytes(buf, buflen);
2152*8ccd4a63SDavid du Colombier 	return e;
2153*8ccd4a63SDavid du Colombier }
2154*8ccd4a63SDavid du Colombier 
2155*8ccd4a63SDavid du Colombier static Elem
mkbits(uchar * buf,int buflen)2156*8ccd4a63SDavid du Colombier mkbits(uchar *buf, int buflen)
2157*8ccd4a63SDavid du Colombier {
2158*8ccd4a63SDavid du Colombier 	Elem e;
2159*8ccd4a63SDavid du Colombier 
2160*8ccd4a63SDavid du Colombier 	e.tag.class = Universal;
2161*8ccd4a63SDavid du Colombier 	e.tag.num = BIT_STRING;
2162*8ccd4a63SDavid du Colombier 	e.val.tag = VBitString;
2163*8ccd4a63SDavid du Colombier 	e.val.u.bitstringval = makebits(buf, buflen, 0);
2164*8ccd4a63SDavid du Colombier 	return e;
2165*8ccd4a63SDavid du Colombier }
2166*8ccd4a63SDavid du Colombier 
2167*8ccd4a63SDavid du Colombier static Elem
mkutc(long t)2168*8ccd4a63SDavid du Colombier mkutc(long t)
2169*8ccd4a63SDavid du Colombier {
2170*8ccd4a63SDavid du Colombier 	Elem e;
2171*8ccd4a63SDavid du Colombier 	char utc[50];
2172*8ccd4a63SDavid du Colombier 	Tm *tm = gmtime(t);
2173*8ccd4a63SDavid du Colombier 
2174*8ccd4a63SDavid du Colombier 	e.tag.class = Universal;
2175*8ccd4a63SDavid du Colombier 	e.tag.num = UTCTime;
2176*8ccd4a63SDavid du Colombier 	e.val.tag = VString;
2177*8ccd4a63SDavid du Colombier 	snprint(utc, 50, "%.2d%.2d%.2d%.2d%.2d%.2dZ",
2178*8ccd4a63SDavid du Colombier 		tm->year % 100, tm->mon+1, tm->mday, tm->hour, tm->min, tm->sec);
2179*8ccd4a63SDavid du Colombier 	e.val.u.stringval = estrdup(utc);
2180*8ccd4a63SDavid du Colombier 	return e;
2181*8ccd4a63SDavid du Colombier }
2182*8ccd4a63SDavid du Colombier 
2183*8ccd4a63SDavid du Colombier static Elem
mkoid(Ints * oid)2184*8ccd4a63SDavid du Colombier mkoid(Ints *oid)
2185*8ccd4a63SDavid du Colombier {
2186*8ccd4a63SDavid du Colombier 	Elem e;
2187*8ccd4a63SDavid du Colombier 
2188*8ccd4a63SDavid du Colombier 	e.tag.class = Universal;
2189*8ccd4a63SDavid du Colombier 	e.tag.num = OBJECT_ID;
2190*8ccd4a63SDavid du Colombier 	e.val.tag = VObjId;
2191*8ccd4a63SDavid du Colombier 	e.val.u.objidval = makeints(oid->data, oid->len);
2192*8ccd4a63SDavid du Colombier 	return e;
2193*8ccd4a63SDavid du Colombier }
2194*8ccd4a63SDavid du Colombier 
2195*8ccd4a63SDavid du Colombier static Elem
mkseq(Elist * el)2196*8ccd4a63SDavid du Colombier mkseq(Elist *el)
2197*8ccd4a63SDavid du Colombier {
2198*8ccd4a63SDavid du Colombier 	Elem e;
2199*8ccd4a63SDavid du Colombier 
2200*8ccd4a63SDavid du Colombier 	e.tag.class = Universal;
2201*8ccd4a63SDavid du Colombier 	e.tag.num = SEQUENCE;
2202*8ccd4a63SDavid du Colombier 	e.val.tag = VSeq;
2203*8ccd4a63SDavid du Colombier 	e.val.u.seqval = el;
2204*8ccd4a63SDavid du Colombier 	return e;
2205*8ccd4a63SDavid du Colombier }
2206*8ccd4a63SDavid du Colombier 
2207*8ccd4a63SDavid du Colombier static Elem
mkset(Elist * el)2208*8ccd4a63SDavid du Colombier mkset(Elist *el)
2209*8ccd4a63SDavid du Colombier {
2210*8ccd4a63SDavid du Colombier 	Elem e;
2211*8ccd4a63SDavid du Colombier 
2212*8ccd4a63SDavid du Colombier 	e.tag.class = Universal;
2213*8ccd4a63SDavid du Colombier 	e.tag.num = SETOF;
2214*8ccd4a63SDavid du Colombier 	e.val.tag = VSet;
2215*8ccd4a63SDavid du Colombier 	e.val.u.setval = el;
2216*8ccd4a63SDavid du Colombier 	return e;
2217*8ccd4a63SDavid du Colombier }
2218*8ccd4a63SDavid du Colombier 
2219*8ccd4a63SDavid du Colombier static Elem
mkalg(int alg)2220*8ccd4a63SDavid du Colombier mkalg(int alg)
2221*8ccd4a63SDavid du Colombier {
2222*8ccd4a63SDavid du Colombier 	return mkseq(mkel(mkoid(alg_oid_tab[alg]), mkel(Null(), nil)));
2223*8ccd4a63SDavid du Colombier }
2224*8ccd4a63SDavid du Colombier 
2225*8ccd4a63SDavid du Colombier typedef struct Ints7pref {
2226*8ccd4a63SDavid du Colombier 	int		len;
2227*8ccd4a63SDavid du Colombier 	int		data[7];
2228*8ccd4a63SDavid du Colombier 	char	prefix[4];
2229*8ccd4a63SDavid du Colombier } Ints7pref;
2230*8ccd4a63SDavid du Colombier Ints7pref DN_oid[] = {
2231*8ccd4a63SDavid du Colombier 	{4, 2, 5, 4, 6, 0, 0, 0,  "C="},
2232*8ccd4a63SDavid du Colombier 	{4, 2, 5, 4, 8, 0, 0, 0,  "ST="},
2233*8ccd4a63SDavid du Colombier 	{4, 2, 5, 4, 7, 0, 0, 0,  "L="},
2234*8ccd4a63SDavid du Colombier 	{4, 2, 5, 4, 10, 0, 0, 0, "O="},
2235*8ccd4a63SDavid du Colombier 	{4, 2, 5, 4, 11, 0, 0, 0, "OU="},
2236*8ccd4a63SDavid du Colombier 	{4, 2, 5, 4, 3, 0, 0, 0,  "CN="},
2237*8ccd4a63SDavid du Colombier  	{7, 1,2,840,113549,1,9,1, "E="},
2238*8ccd4a63SDavid du Colombier };
2239*8ccd4a63SDavid du Colombier 
2240*8ccd4a63SDavid du Colombier static Elem
mkname(Ints7pref * oid,char * subj)2241*8ccd4a63SDavid du Colombier mkname(Ints7pref *oid, char *subj)
2242*8ccd4a63SDavid du Colombier {
2243*8ccd4a63SDavid du Colombier 	return mkset(mkel(mkseq(mkel(mkoid((Ints*)oid), mkel(mkstring(subj), nil))), nil));
2244*8ccd4a63SDavid du Colombier }
2245*8ccd4a63SDavid du Colombier 
2246*8ccd4a63SDavid du Colombier static Elem
mkDN(char * dn)2247*8ccd4a63SDavid du Colombier mkDN(char *dn)
2248*8ccd4a63SDavid du Colombier {
2249*8ccd4a63SDavid du Colombier 	int i, j, nf;
2250*8ccd4a63SDavid du Colombier 	char *f[20], *prefix, *d2 = estrdup(dn);
2251*8ccd4a63SDavid du Colombier 	Elist* el = nil;
2252*8ccd4a63SDavid du Colombier 
2253*8ccd4a63SDavid du Colombier 	nf = tokenize(d2, f, nelem(f));
2254*8ccd4a63SDavid du Colombier 	for(i=nf-1; i>=0; i--){
2255*8ccd4a63SDavid du Colombier 		for(j=0; j<nelem(DN_oid); j++){
2256*8ccd4a63SDavid du Colombier 			prefix = DN_oid[j].prefix;
2257*8ccd4a63SDavid du Colombier 			if(strncmp(f[i],prefix,strlen(prefix))==0){
2258*8ccd4a63SDavid du Colombier 				el = mkel(mkname(&DN_oid[j],f[i]+strlen(prefix)), el);
2259*8ccd4a63SDavid du Colombier 				break;
2260*8ccd4a63SDavid du Colombier 			}
2261*8ccd4a63SDavid du Colombier 		}
2262*8ccd4a63SDavid du Colombier 	}
2263*8ccd4a63SDavid du Colombier 	free(d2);
2264*8ccd4a63SDavid du Colombier 	return mkseq(el);
2265*8ccd4a63SDavid du Colombier }
2266*8ccd4a63SDavid du Colombier 
2267*8ccd4a63SDavid du Colombier 
2268*8ccd4a63SDavid du Colombier uchar*
X509gen(RSApriv * priv,char * subj,ulong valid[2],int * certlen)2269*8ccd4a63SDavid du Colombier X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
2270*8ccd4a63SDavid du Colombier {
2271*8ccd4a63SDavid du Colombier 	int serial = 0;
2272*8ccd4a63SDavid du Colombier 	uchar *cert = nil;
2273*8ccd4a63SDavid du Colombier 	RSApub *pk = rsaprivtopub(priv);
2274*8ccd4a63SDavid du Colombier 	Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;
2275*8ccd4a63SDavid du Colombier 	Elem e, certinfo, issuer, subject, pubkey, validity, sig;
2276*8ccd4a63SDavid du Colombier 	uchar digest[MD5dlen], *buf;
2277*8ccd4a63SDavid du Colombier 	int buflen;
2278*8ccd4a63SDavid du Colombier 	mpint *pkcs1;
2279*8ccd4a63SDavid du Colombier 
2280*8ccd4a63SDavid du Colombier 	e.val.tag = VInt;  /* so freevalfields at errret is no-op */
2281*8ccd4a63SDavid du Colombier 	issuer = mkDN(subj);
2282*8ccd4a63SDavid du Colombier 	subject = mkDN(subj);
2283*8ccd4a63SDavid du Colombier 	pubkey = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
2284*8ccd4a63SDavid du Colombier 	if(encode(pubkey, &pkbytes) != ASN_OK)
2285*8ccd4a63SDavid du Colombier 		goto errret;
2286*8ccd4a63SDavid du Colombier 	freevalfields(&pubkey.val);
2287*8ccd4a63SDavid du Colombier 	pubkey = mkseq(
2288*8ccd4a63SDavid du Colombier 		mkel(mkalg(ALG_rsaEncryption),
2289*8ccd4a63SDavid du Colombier 		mkel(mkbits(pkbytes->data, pkbytes->len),
2290*8ccd4a63SDavid du Colombier 		nil)));
2291*8ccd4a63SDavid du Colombier 	freebytes(pkbytes);
2292*8ccd4a63SDavid du Colombier 	validity = mkseq(
2293*8ccd4a63SDavid du Colombier 		mkel(mkutc(valid[0]),
2294*8ccd4a63SDavid du Colombier 		mkel(mkutc(valid[1]),
2295*8ccd4a63SDavid du Colombier 		nil)));
2296*8ccd4a63SDavid du Colombier 	certinfo = mkseq(
2297*8ccd4a63SDavid du Colombier 		mkel(mkint(serial),
2298*8ccd4a63SDavid du Colombier 		mkel(mkalg(ALG_md5WithRSAEncryption),
2299*8ccd4a63SDavid du Colombier 		mkel(issuer,
2300*8ccd4a63SDavid du Colombier 		mkel(validity,
2301*8ccd4a63SDavid du Colombier 		mkel(subject,
2302*8ccd4a63SDavid du Colombier 		mkel(pubkey,
2303*8ccd4a63SDavid du Colombier 		nil)))))));
2304*8ccd4a63SDavid du Colombier 	if(encode(certinfo, &certinfobytes) != ASN_OK)
2305*8ccd4a63SDavid du Colombier 		goto errret;
2306*8ccd4a63SDavid du Colombier 	md5(certinfobytes->data, certinfobytes->len, digest, 0);
2307*8ccd4a63SDavid du Colombier 	freebytes(certinfobytes);
2308*8ccd4a63SDavid du Colombier 	sig = mkseq(
2309*8ccd4a63SDavid du Colombier 		mkel(mkalg(ALG_md5),
2310*8ccd4a63SDavid du Colombier 		mkel(mkoctet(digest, MD5dlen),
2311*8ccd4a63SDavid du Colombier 		nil)));
2312*8ccd4a63SDavid du Colombier 	if(encode(sig, &sigbytes) != ASN_OK)
2313*8ccd4a63SDavid du Colombier 		goto errret;
2314*8ccd4a63SDavid du Colombier 	pkcs1 = pkcs1pad(sigbytes, pk->n);
2315*8ccd4a63SDavid du Colombier 	freebytes(sigbytes);
2316*8ccd4a63SDavid du Colombier 	rsadecrypt(priv, pkcs1, pkcs1);
2317*8ccd4a63SDavid du Colombier 	buflen = mptobe(pkcs1, nil, 0, &buf);
2318*8ccd4a63SDavid du Colombier 	mpfree(pkcs1);
2319*8ccd4a63SDavid du Colombier 	e = mkseq(
2320*8ccd4a63SDavid du Colombier 		mkel(certinfo,
2321*8ccd4a63SDavid du Colombier 		mkel(mkalg(ALG_md5WithRSAEncryption),
2322*8ccd4a63SDavid du Colombier 		mkel(mkbits(buf, buflen),
2323*8ccd4a63SDavid du Colombier 		nil))));
2324*8ccd4a63SDavid du Colombier 	free(buf);
2325*8ccd4a63SDavid du Colombier 	if(encode(e, &certbytes) != ASN_OK)
2326*8ccd4a63SDavid du Colombier 		goto errret;
2327*8ccd4a63SDavid du Colombier 	if(certlen)
2328*8ccd4a63SDavid du Colombier 		*certlen = certbytes->len;
2329*8ccd4a63SDavid du Colombier 	cert = certbytes->data;
2330*8ccd4a63SDavid du Colombier errret:
2331*8ccd4a63SDavid du Colombier 	freevalfields(&e.val);
2332*8ccd4a63SDavid du Colombier 	return cert;
2333*8ccd4a63SDavid du Colombier }
2334*8ccd4a63SDavid du Colombier 
2335*8ccd4a63SDavid du Colombier uchar*
X509req(RSApriv * priv,char * subj,int * certlen)2336*8ccd4a63SDavid du Colombier X509req(RSApriv *priv, char *subj, int *certlen)
2337*8ccd4a63SDavid du Colombier {
2338*8ccd4a63SDavid du Colombier 	/* RFC 2314, PKCS #10 Certification Request Syntax */
2339*8ccd4a63SDavid du Colombier 	int version = 0;
2340*8ccd4a63SDavid du Colombier 	uchar *cert = nil;
2341*8ccd4a63SDavid du Colombier 	RSApub *pk = rsaprivtopub(priv);
2342*8ccd4a63SDavid du Colombier 	Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;
2343*8ccd4a63SDavid du Colombier 	Elem e, certinfo, subject, pubkey, sig;
2344*8ccd4a63SDavid du Colombier 	uchar digest[MD5dlen], *buf;
2345*8ccd4a63SDavid du Colombier 	int buflen;
2346*8ccd4a63SDavid du Colombier 	mpint *pkcs1;
2347*8ccd4a63SDavid du Colombier 
2348*8ccd4a63SDavid du Colombier 	e.val.tag = VInt;  /* so freevalfields at errret is no-op */
2349*8ccd4a63SDavid du Colombier 	subject = mkDN(subj);
2350*8ccd4a63SDavid du Colombier 	pubkey = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));
2351*8ccd4a63SDavid du Colombier 	if(encode(pubkey, &pkbytes) != ASN_OK)
2352*8ccd4a63SDavid du Colombier 		goto errret;
2353*8ccd4a63SDavid du Colombier 	freevalfields(&pubkey.val);
2354*8ccd4a63SDavid du Colombier 	pubkey = mkseq(
2355*8ccd4a63SDavid du Colombier 		mkel(mkalg(ALG_rsaEncryption),
2356*8ccd4a63SDavid du Colombier 		mkel(mkbits(pkbytes->data, pkbytes->len),
2357*8ccd4a63SDavid du Colombier 		nil)));
2358*8ccd4a63SDavid du Colombier 	freebytes(pkbytes);
2359*8ccd4a63SDavid du Colombier 	certinfo = mkseq(
2360*8ccd4a63SDavid du Colombier 		mkel(mkint(version),
2361*8ccd4a63SDavid du Colombier 		mkel(subject,
2362*8ccd4a63SDavid du Colombier 		mkel(pubkey,
2363*8ccd4a63SDavid du Colombier 		nil))));
2364*8ccd4a63SDavid du Colombier 	if(encode(certinfo, &certinfobytes) != ASN_OK)
2365*8ccd4a63SDavid du Colombier 		goto errret;
2366*8ccd4a63SDavid du Colombier 	md5(certinfobytes->data, certinfobytes->len, digest, 0);
2367*8ccd4a63SDavid du Colombier 	freebytes(certinfobytes);
2368*8ccd4a63SDavid du Colombier 	sig = mkseq(
2369*8ccd4a63SDavid du Colombier 		mkel(mkalg(ALG_md5),
2370*8ccd4a63SDavid du Colombier 		mkel(mkoctet(digest, MD5dlen),
2371*8ccd4a63SDavid du Colombier 		nil)));
2372*8ccd4a63SDavid du Colombier 	if(encode(sig, &sigbytes) != ASN_OK)
2373*8ccd4a63SDavid du Colombier 		goto errret;
2374*8ccd4a63SDavid du Colombier 	pkcs1 = pkcs1pad(sigbytes, pk->n);
2375*8ccd4a63SDavid du Colombier 	freebytes(sigbytes);
2376*8ccd4a63SDavid du Colombier 	rsadecrypt(priv, pkcs1, pkcs1);
2377*8ccd4a63SDavid du Colombier 	buflen = mptobe(pkcs1, nil, 0, &buf);
2378*8ccd4a63SDavid du Colombier 	mpfree(pkcs1);
2379*8ccd4a63SDavid du Colombier 	e = mkseq(
2380*8ccd4a63SDavid du Colombier 		mkel(certinfo,
2381*8ccd4a63SDavid du Colombier 		mkel(mkalg(ALG_md5),
2382*8ccd4a63SDavid du Colombier 		mkel(mkbits(buf, buflen),
2383*8ccd4a63SDavid du Colombier 		nil))));
2384*8ccd4a63SDavid du Colombier 	free(buf);
2385*8ccd4a63SDavid du Colombier 	if(encode(e, &certbytes) != ASN_OK)
2386*8ccd4a63SDavid du Colombier 		goto errret;
2387*8ccd4a63SDavid du Colombier 	if(certlen)
2388*8ccd4a63SDavid du Colombier 		*certlen = certbytes->len;
2389*8ccd4a63SDavid du Colombier 	cert = certbytes->data;
2390*8ccd4a63SDavid du Colombier errret:
2391*8ccd4a63SDavid du Colombier 	freevalfields(&e.val);
2392*8ccd4a63SDavid du Colombier 	return cert;
2393*8ccd4a63SDavid du Colombier }
2394*8ccd4a63SDavid du Colombier 
2395*8ccd4a63SDavid du Colombier static char*
tagdump(Tag tag)2396*8ccd4a63SDavid du Colombier tagdump(Tag tag)
2397*8ccd4a63SDavid du Colombier {
2398*8ccd4a63SDavid du Colombier 	if(tag.class != Universal)
2399*8ccd4a63SDavid du Colombier 		return smprint("class%d,num%d", tag.class, tag.num);
2400*8ccd4a63SDavid du Colombier 	switch(tag.num){
2401*8ccd4a63SDavid du Colombier 		case BOOLEAN: return "BOOLEAN"; break;
2402*8ccd4a63SDavid du Colombier 		case INTEGER: return "INTEGER"; break;
2403*8ccd4a63SDavid du Colombier 		case BIT_STRING: return "BIT STRING"; break;
2404*8ccd4a63SDavid du Colombier 		case OCTET_STRING: return "OCTET STRING"; break;
2405*8ccd4a63SDavid du Colombier 		case NULLTAG: return "NULLTAG"; break;
2406*8ccd4a63SDavid du Colombier 		case OBJECT_ID: return "OID"; break;
2407*8ccd4a63SDavid du Colombier 		case ObjectDescriptor: return "OBJECT_DES"; break;
2408*8ccd4a63SDavid du Colombier 		case EXTERNAL: return "EXTERNAL"; break;
2409*8ccd4a63SDavid du Colombier 		case REAL: return "REAL"; break;
2410*8ccd4a63SDavid du Colombier 		case ENUMERATED: return "ENUMERATED"; break;
2411*8ccd4a63SDavid du Colombier 		case EMBEDDED_PDV: return "EMBEDDED PDV"; break;
2412*8ccd4a63SDavid du Colombier 		case SEQUENCE: return "SEQUENCE"; break;
2413*8ccd4a63SDavid du Colombier 		case SETOF: return "SETOF"; break;
2414*8ccd4a63SDavid du Colombier 		case NumericString: return "NumericString"; break;
2415*8ccd4a63SDavid du Colombier 		case PrintableString: return "PrintableString"; break;
2416*8ccd4a63SDavid du Colombier 		case TeletexString: return "TeletexString"; break;
2417*8ccd4a63SDavid du Colombier 		case VideotexString: return "VideotexString"; break;
2418*8ccd4a63SDavid du Colombier 		case IA5String: return "IA5String"; break;
2419*8ccd4a63SDavid du Colombier 		case UTCTime: return "UTCTime"; break;
2420*8ccd4a63SDavid du Colombier 		case GeneralizedTime: return "GeneralizedTime"; break;
2421*8ccd4a63SDavid du Colombier 		case GraphicString: return "GraphicString"; break;
2422*8ccd4a63SDavid du Colombier 		case VisibleString: return "VisibleString"; break;
2423*8ccd4a63SDavid du Colombier 		case GeneralString: return "GeneralString"; break;
2424*8ccd4a63SDavid du Colombier 		case UniversalString: return "UniversalString"; break;
2425*8ccd4a63SDavid du Colombier 		case BMPString: return "BMPString"; break;
2426*8ccd4a63SDavid du Colombier 		default:
2427*8ccd4a63SDavid du Colombier 			return smprint("Universal,num%d", tag.num);
2428*8ccd4a63SDavid du Colombier 	}
2429*8ccd4a63SDavid du Colombier }
2430*8ccd4a63SDavid du Colombier 
2431*8ccd4a63SDavid du Colombier static void
edump(Elem e)2432*8ccd4a63SDavid du Colombier edump(Elem e)
2433*8ccd4a63SDavid du Colombier {
2434*8ccd4a63SDavid du Colombier 	Value v;
2435*8ccd4a63SDavid du Colombier 	Elist *el;
2436*8ccd4a63SDavid du Colombier 	int i;
2437*8ccd4a63SDavid du Colombier 
2438*8ccd4a63SDavid du Colombier 	print("%s{", tagdump(e.tag));
2439*8ccd4a63SDavid du Colombier 	v = e.val;
2440*8ccd4a63SDavid du Colombier 	switch(v.tag){
2441*8ccd4a63SDavid du Colombier 	case VBool: print("Bool %d",v.u.boolval); break;
2442*8ccd4a63SDavid du Colombier 	case VInt: print("Int %d",v.u.intval); break;
2443*8ccd4a63SDavid du Colombier 	case VOctets: print("Octets[%d] %.2x%.2x...",v.u.octetsval->len,v.u.octetsval->data[0],v.u.octetsval->data[1]); break;
2444*8ccd4a63SDavid du Colombier 	case VBigInt: print("BigInt[%d] %.2x%.2x...",v.u.bigintval->len,v.u.bigintval->data[0],v.u.bigintval->data[1]); break;
2445*8ccd4a63SDavid du Colombier 	case VReal: print("Real..."); break;
2446*8ccd4a63SDavid du Colombier 	case VOther: print("Other..."); break;
2447*8ccd4a63SDavid du Colombier 	case VBitString: print("BitString..."); break;
2448*8ccd4a63SDavid du Colombier 	case VNull: print("Null"); break;
2449*8ccd4a63SDavid du Colombier 	case VEOC: print("EOC..."); break;
2450*8ccd4a63SDavid du Colombier 	case VObjId: print("ObjId");
2451*8ccd4a63SDavid du Colombier 		for(i = 0; i<v.u.objidval->len; i++)
2452*8ccd4a63SDavid du Colombier 			print(" %d", v.u.objidval->data[i]);
2453*8ccd4a63SDavid du Colombier 		break;
2454*8ccd4a63SDavid du Colombier 	case VString: print("String \"%s\"",v.u.stringval); break;
2455*8ccd4a63SDavid du Colombier 	case VSeq: print("Seq\n");
2456*8ccd4a63SDavid du Colombier 		for(el = v.u.seqval; el!=nil; el = el->tl)
2457*8ccd4a63SDavid du Colombier 			edump(el->hd);
2458*8ccd4a63SDavid du Colombier 		break;
2459*8ccd4a63SDavid du Colombier 	case VSet: print("Set\n");
2460*8ccd4a63SDavid du Colombier 		for(el = v.u.setval; el!=nil; el = el->tl)
2461*8ccd4a63SDavid du Colombier 			edump(el->hd);
2462*8ccd4a63SDavid du Colombier 		break;
2463*8ccd4a63SDavid du Colombier 	}
2464*8ccd4a63SDavid du Colombier 	print("}\n");
2465*8ccd4a63SDavid du Colombier }
2466*8ccd4a63SDavid du Colombier 
2467*8ccd4a63SDavid du Colombier void
asn1dump(uchar * der,int len)2468*8ccd4a63SDavid du Colombier asn1dump(uchar *der, int len)
2469*8ccd4a63SDavid du Colombier {
2470*8ccd4a63SDavid du Colombier 	Elem e;
2471*8ccd4a63SDavid du Colombier 
2472*8ccd4a63SDavid du Colombier 	if(decode(der, len, &e) != ASN_OK){
2473*8ccd4a63SDavid du Colombier 		print("didn't parse\n");
2474*8ccd4a63SDavid du Colombier 		exits("didn't parse");
2475*8ccd4a63SDavid du Colombier 	}
2476*8ccd4a63SDavid du Colombier 	edump(e);
2477*8ccd4a63SDavid du Colombier }
2478*8ccd4a63SDavid du Colombier 
2479*8ccd4a63SDavid du Colombier void
X509dump(uchar * cert,int ncert)2480*8ccd4a63SDavid du Colombier X509dump(uchar *cert, int ncert)
2481*8ccd4a63SDavid du Colombier {
2482*8ccd4a63SDavid du Colombier 	char *e;
2483*8ccd4a63SDavid du Colombier 	Bytes *b;
2484*8ccd4a63SDavid du Colombier 	CertX509 *c;
2485*8ccd4a63SDavid du Colombier 	RSApub *pk;
2486*8ccd4a63SDavid du Colombier 	uchar digest[SHA1dlen];
2487*8ccd4a63SDavid du Colombier 	Elem *sigalg;
2488*8ccd4a63SDavid du Colombier 
2489*8ccd4a63SDavid du Colombier 	print("begin X509dump\n");
2490*8ccd4a63SDavid du Colombier 	b = makebytes(cert, ncert);
2491*8ccd4a63SDavid du Colombier 	c = decode_cert(b);
2492*8ccd4a63SDavid du Colombier 	if(c != nil)
2493*8ccd4a63SDavid du Colombier 		digest_certinfo(b, digestalg[c->signature_alg], digest);
2494*8ccd4a63SDavid du Colombier 	freebytes(b);
2495*8ccd4a63SDavid du Colombier 	if(c == nil){
2496*8ccd4a63SDavid du Colombier 		print("cannot decode cert");
2497*8ccd4a63SDavid du Colombier 		return;
2498*8ccd4a63SDavid du Colombier 	}
2499*8ccd4a63SDavid du Colombier 
2500*8ccd4a63SDavid du Colombier 	print("serial %d\n", c->serial);
2501*8ccd4a63SDavid du Colombier 	print("issuer %s\n", c->issuer);
2502*8ccd4a63SDavid du Colombier 	print("validity %s %s\n", c->validity_start, c->validity_end);
2503*8ccd4a63SDavid du Colombier 	print("subject %s\n", c->subject);
2504*8ccd4a63SDavid du Colombier 	pk = decode_rsapubkey(c->publickey);
2505*8ccd4a63SDavid du Colombier 	print("pubkey e=%B n(%d)=%B\n", pk->ek, mpsignif(pk->n), pk->n);
2506*8ccd4a63SDavid du Colombier 
2507*8ccd4a63SDavid du Colombier 	print("sigalg=%d digest=%.*H\n", c->signature_alg, MD5dlen, digest);
2508*8ccd4a63SDavid du Colombier 	e = verify_signature(c->signature, pk, digest, &sigalg);
2509*8ccd4a63SDavid du Colombier 	if(e==nil){
2510*8ccd4a63SDavid du Colombier 		e = "nil (meaning ok)";
2511*8ccd4a63SDavid du Colombier 		print("sigalg=\n");
2512*8ccd4a63SDavid du Colombier 		if(sigalg)
2513*8ccd4a63SDavid du Colombier 			edump(*sigalg);
2514*8ccd4a63SDavid du Colombier 	}
2515*8ccd4a63SDavid du Colombier 	print("self-signed verify_signature returns: %s\n", e);
2516*8ccd4a63SDavid du Colombier 
2517*8ccd4a63SDavid du Colombier 	rsapubfree(pk);
2518*8ccd4a63SDavid du Colombier 	freecert(c);
2519*8ccd4a63SDavid du Colombier 	print("end X509dump\n");
2520*8ccd4a63SDavid du Colombier }
2521