1/* crypto/asn1/a_int.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the rouines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <stdlib.h>
60#include <stdio.h>
61#include <string.h>
62#include <time.h>
63
64#if 0
65#include "cryptlib.h"
66#include <openssl/asn1.h>
67#include <openssl/bn.h>
68#else
69#include "cs-asn1.h"
70#include "cs-bn.h"
71#endif
72
73ASN1_INTEGER *ASN1_INTEGER_dup(ASN1_INTEGER *x)
74{ return M_ASN1_INTEGER_dup(x);}
75
76int ASN1_INTEGER_cmp(ASN1_INTEGER *x, ASN1_INTEGER *y)
77	{
78	int neg, ret;
79	/* Compare signs */
80	neg = x->type & V_ASN1_NEG;
81	if (neg != (y->type & V_ASN1_NEG))
82		{
83		if (neg)
84			return -1;
85		else
86			return 1;
87		}
88
89	ret = ASN1_STRING_cmp(x, y);
90
91	if (neg)
92		return -ret;
93	else
94		return ret;
95	}
96
97
98/*
99 * This converts an ASN1 INTEGER into its content encoding.
100 * The internal representation is an ASN1_STRING whose data is a big endian
101 * representation of the value, ignoring the sign. The sign is determined by
102 * the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
103 *
104 * Positive integers are no problem: they are almost the same as the DER
105 * encoding, except if the first byte is >= 0x80 we need to add a zero pad.
106 *
107 * Negative integers are a bit trickier...
108 * The DER representation of negative integers is in 2s complement form.
109 * The internal form is converted by complementing each octet and finally
110 * adding one to the result. This can be done less messily with a little trick.
111 * If the internal form has trailing zeroes then they will become FF by the
112 * complement and 0 by the add one (due to carry) so just copy as many trailing
113 * zeros to the destination as there are in the source. The carry will add one
114 * to the last none zero octet: so complement this octet and add one and finally
115 * complement any left over until you get to the start of the string.
116 *
117 * Padding is a little trickier too. If the first bytes is > 0x80 then we pad
118 * with 0xff. However if the first byte is 0x80 and one of the following bytes
119 * is non-zero we pad with 0xff. The reason for this distinction is that 0x80
120 * followed by optional zeros isn't padded.
121 */
122
123int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
124	{
125	int pad=0,ret,i,neg;
126	unsigned char *p,*n,pb=0;
127
128	if ((a == NULL) || (a->data == NULL)) return(0);
129	neg=a->type & V_ASN1_NEG;
130	if (a->length == 0)
131		ret=1;
132	else
133		{
134		ret=a->length;
135		i=a->data[0];
136		if (!neg && (i > 127)) {
137			pad=1;
138			pb=0;
139		} else if(neg) {
140			if(i>128) {
141				pad=1;
142				pb=0xFF;
143			} else if(i == 128) {
144			/*
145			 * Special case: if any other bytes non zero we pad:
146			 * otherwise we don't.
147			 */
148				for(i = 1; i < a->length; i++) if(a->data[i]) {
149						pad=1;
150						pb=0xFF;
151						break;
152				}
153			}
154		}
155		ret+=pad;
156		}
157	if (pp == NULL) return(ret);
158	p= *pp;
159
160	if (pad) *(p++)=pb;
161	if (a->length == 0) *(p++)=0;
162	else if (!neg) memcpy(p,a->data,(unsigned int)a->length);
163	else {
164		/* Begin at the end of the encoding */
165		n=a->data + a->length - 1;
166		p += a->length - 1;
167		i = a->length;
168		/* Copy zeros to destination as long as source is zero */
169		while(!*n) {
170			*(p--) = 0;
171			n--;
172			i--;
173		}
174		/* Complement and increment next octet */
175		*(p--) = ((*(n--)) ^ 0xff) + 1;
176		i--;
177		/* Complement any octets left */
178		for(;i > 0; i--) *(p--) = *(n--) ^ 0xff;
179	}
180
181	*pp+=ret;
182	return(ret);
183	}
184
185/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */
186
187ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
188	     long len)
189	{
190	ASN1_INTEGER *ret=NULL;
191	const unsigned char *p, *pend;
192	unsigned char *to,*s;
193	int i;
194
195	if ((a == NULL) || ((*a) == NULL))
196		{
197		if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
198		ret->type=V_ASN1_INTEGER;
199		}
200	else
201		ret=(*a);
202
203	p= *pp;
204	pend = p + len;
205
206	/* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
207	 * signifies a missing NULL parameter. */
208	s=(unsigned char *)malloc((int)len+1);
209	if (s == NULL)
210		{
211		/* i=ERR_R_MALLOC_FAILURE; */
212		i = -1;
213		goto err;
214		}
215	to=s;
216	if(!len) {
217		/* Strictly speaking this is an illegal INTEGER but we
218		 * tolerate it.
219		 */
220		ret->type=V_ASN1_INTEGER;
221	} else if (*p & 0x80) /* a negative number */
222		{
223		ret->type=V_ASN1_NEG_INTEGER;
224		if ((*p == 0xff) && (len != 1)) {
225			p++;
226			len--;
227		}
228		i = len;
229		p += i - 1;
230		to += i - 1;
231		while((!*p) && i) {
232			*(to--) = 0;
233			i--;
234			p--;
235		}
236		/* Special case: if all zeros then the number will be of
237		 * the form FF followed by n zero bytes: this corresponds to
238		 * 1 followed by n zero bytes. We've already written n zeros
239		 * so we just append an extra one and set the first byte to
240		 * a 1. This is treated separately because it is the only case
241		 * where the number of bytes is larger than len.
242		 */
243		if(!i) {
244			*s = 1;
245			s[len] = 0;
246			len++;
247		} else {
248			*(to--) = (*(p--) ^ 0xff) + 1;
249			i--;
250			for(;i > 0; i--) *(to--) = *(p--) ^ 0xff;
251		}
252	} else {
253		ret->type=V_ASN1_INTEGER;
254		if ((*p == 0) && (len != 1))
255			{
256			p++;
257			len--;
258			}
259		memcpy(s,p,(int)len);
260	}
261
262	if (ret->data != NULL) free(ret->data);
263	ret->data=s;
264	ret->length=(int)len;
265	if (a != NULL) (*a)=ret;
266	*pp=pend;
267	return(ret);
268err:
269	/* ASN1err(ASN1_F_C2I_ASN1_INTEGER,i); */
270	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
271		M_ASN1_INTEGER_free(ret);
272	return(NULL);
273	}
274
275
276/* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of
277 * ASN1 integers: some broken software can encode a positive INTEGER
278 * with its MSB set as negative (it doesn't add a padding zero).
279 */
280
281ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
282	     long length)
283	{
284	ASN1_INTEGER *ret=NULL;
285	const unsigned char *p;
286	unsigned char *s;
287	long len;
288	int inf,tag,xclass;
289	int i;
290
291	if ((a == NULL) || ((*a) == NULL))
292		{
293		if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
294		ret->type=V_ASN1_INTEGER;
295		}
296	else
297		ret=(*a);
298
299	p= *pp;
300	inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
301	if (inf & 0x80)
302		{
303		i=ASN1_R_BAD_OBJECT_HEADER;
304		goto err;
305		}
306
307	if (tag != V_ASN1_INTEGER)
308		{
309		i=ASN1_R_EXPECTING_AN_INTEGER;
310		goto err;
311		}
312
313	/* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
314	 * signifies a missing NULL parameter. */
315	s=(unsigned char *)malloc((int)len+1);
316	if (s == NULL)
317		{
318		/* i=ERR_R_MALLOC_FAILURE; */
319		i = -1;
320		goto err;
321		}
322	ret->type=V_ASN1_INTEGER;
323	if(len) {
324		if ((*p == 0) && (len != 1))
325			{
326			p++;
327			len--;
328			}
329		memcpy(s,p,(int)len);
330		p+=len;
331	}
332
333	if (ret->data != NULL) free(ret->data);
334	ret->data=s;
335	ret->length=(int)len;
336	if (a != NULL) (*a)=ret;
337	*pp=p;
338	return(ret);
339err:
340	/* ASN1err(ASN1_F_D2I_ASN1_UINTEGER,i); */
341	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
342		M_ASN1_INTEGER_free(ret);
343	return(NULL);
344	}
345
346int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
347	{
348	int j,k;
349	unsigned int i;
350	unsigned char buf[sizeof(long)+1];
351	long d;
352
353	a->type=V_ASN1_INTEGER;
354	if (a->length < (int)(sizeof(long)+1))
355		{
356		if (a->data != NULL)
357			free(a->data);
358		if ((a->data=(unsigned char *)malloc(sizeof(long)+1)) != NULL)
359			memset((char *)a->data,0,sizeof(long)+1);
360		}
361	if (a->data == NULL)
362		{
363		/* ASN1err(ASN1_F_ASN1_INTEGER_SET,ERR_R_MALLOC_FAILURE); */
364		return(0);
365		}
366	d=v;
367	if (d < 0)
368		{
369		d= -d;
370		a->type=V_ASN1_NEG_INTEGER;
371		}
372
373	for (i=0; i<sizeof(long); i++)
374		{
375		if (d == 0) break;
376		buf[i]=(int)d&0xff;
377		d>>=8;
378		}
379	j=0;
380	for (k=i-1; k >=0; k--)
381		a->data[j++]=buf[k];
382	a->length=j;
383	return(1);
384	}
385
386long ASN1_INTEGER_get(ASN1_INTEGER *a)
387	{
388	int neg=0,i;
389	long r=0;
390
391	if (a == NULL) return(0L);
392	i=a->type;
393	if (i == V_ASN1_NEG_INTEGER)
394		neg=1;
395	else if (i != V_ASN1_INTEGER)
396		return -1;
397
398	if (a->length > (int)sizeof(long))
399		{
400		/* hmm... a bit ugly */
401		return(0xffffffffL);
402		}
403	if (a->data == NULL)
404		return 0;
405
406	for (i=0; i<a->length; i++)
407		{
408		r<<=8;
409		r|=(unsigned char)a->data[i];
410		}
411	if (neg) r= -r;
412	return(r);
413	}
414
415ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *bn, ASN1_INTEGER *ai)
416	{
417	ASN1_INTEGER *ret;
418	int len,j;
419
420	if (ai == NULL)
421		ret=M_ASN1_INTEGER_new();
422	else
423		ret=ai;
424	if (ret == NULL)
425		{
426		/* ASN1err(ASN1_F_BN_TO_ASN1_INTEGER,ERR_R_NESTED_ASN1_ERROR); */
427		goto err;
428		}
429	if (BN_is_negative(bn))
430		ret->type = V_ASN1_NEG_INTEGER;
431	else ret->type=V_ASN1_INTEGER;
432	j=BN_num_bits(bn);
433	len=((j == 0)?0:((j/8)+1));
434	if (ret->length < len+4)
435		{
436		unsigned char *new_data=realloc(ret->data, len+4);
437		if (!new_data)
438			{
439			/* ASN1err(ASN1_F_BN_TO_ASN1_INTEGER,ERR_R_MALLOC_FAILURE); */
440			goto err;
441			}
442		ret->data=new_data;
443		}
444	ret->length=BN_bn2bin(bn,ret->data);
445	/* Correct zero case */
446	if(!ret->length)
447		{
448		ret->data[0] = 0;
449		ret->length = 1;
450		}
451	return(ret);
452err:
453	if (ret != ai) M_ASN1_INTEGER_free(ret);
454	return(NULL);
455	}
456
457BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *ai, BIGNUM *bn)
458	{
459	BIGNUM *ret;
460
461	if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
462		/* ASN1err(ASN1_F_ASN1_INTEGER_TO_BN,ASN1_R_BN_LIB); */
463		;
464	else if(ai->type == V_ASN1_NEG_INTEGER)
465		BN_set_negative(ret, 1);
466	return(ret);
467	}
468
469IMPLEMENT_STACK_OF(ASN1_INTEGER)
470IMPLEMENT_ASN1_SET_OF(ASN1_INTEGER)
471