acfc855261bbf0a2a330ddaa06d912886cfd6112
[openssl.git] / crypto / asn1 / a_int.c
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 <stdio.h>
60 #include "cryptlib.h"
61 #include "asn1.h"
62
63 /* ASN1err(ASN1_F_D2I_ASN1_INTEGER,ASN1_R_EXPECTING_AN_INTEGER);
64  */
65
66 int i2d_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
67         {
68         int pad=0,ret,r,i,t;
69         unsigned char *p,*pt,*n,pb=0;
70
71         if ((a == NULL) || (a->data == NULL)) return(0);
72         t=a->type;
73         if (a->length == 0)
74                 ret=1;
75         else
76                 {
77                 ret=a->length;
78                 i=a->data[0];
79                 if ((t == V_ASN1_INTEGER) && (i > 127))
80                         {
81                         pad=1;
82                         pb=0;
83                         }
84                 else if ((t == V_ASN1_NEG_INTEGER) && (i>128))
85                         {
86                         pad=1;
87                         pb=0xFF;
88                         }
89                 ret+=pad;
90                 }
91         r=ASN1_object_size(0,ret,V_ASN1_INTEGER);
92         if (pp == NULL) return(r);
93         p= *pp;
94
95         ASN1_put_object(&p,0,ret,V_ASN1_INTEGER,V_ASN1_UNIVERSAL);
96         if (pad) *(p++)=pb;
97         if (a->length == 0)
98                 *(p++)=0;
99         else if (t == V_ASN1_INTEGER)
100                 {
101                 memcpy(p,a->data,(unsigned int)a->length);
102                 p+=a->length;
103                 }
104         else
105                 {
106                 n=a->data;
107                 pt=p;
108                 for (i=a->length; i>0; i--)
109                         *(p++)= (*(n++)^0xFF)+1;
110                 if (!pad) *pt|=0x80;
111                 }
112
113         *pp=p;
114         return(r);
115         }
116
117 ASN1_INTEGER *d2i_ASN1_INTEGER(ASN1_INTEGER **a, unsigned char **pp,
118              long length)
119         {
120         ASN1_INTEGER *ret=NULL;
121         unsigned char *p,*to,*s;
122         long len;
123         int inf,tag,xclass;
124         int i;
125
126         if ((a == NULL) || ((*a) == NULL))
127                 {
128                 if ((ret=ASN1_INTEGER_new()) == NULL) return(NULL);
129                 ret->type=V_ASN1_INTEGER;
130                 }
131         else
132                 ret=(*a);
133
134         p= *pp;
135         inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
136         if (inf & 0x80)
137                 {
138                 i=ASN1_R_BAD_OBJECT_HEADER;
139                 goto err;
140                 }
141
142         if (tag != V_ASN1_INTEGER)
143                 {
144                 i=ASN1_R_EXPECTING_AN_INTEGER;
145                 goto err;
146                 }
147
148         /* We must Malloc stuff, even for 0 bytes otherwise it
149          * signifies a missing NULL parameter. */
150         s=(unsigned char *)Malloc((int)len+1);
151         if (s == NULL)
152                 {
153                 i=ERR_R_MALLOC_FAILURE;
154                 goto err;
155                 }
156         to=s;
157         if (*p & 0x80) /* a negative number */
158                 {
159                 ret->type=V_ASN1_NEG_INTEGER;
160                 if (*p == 0xff)
161                         {
162                         p++;
163                         len--;
164                         }
165                 for (i=(int)len; i>0; i--)
166                         *(to++)= (*(p++)^0xFF)+1;
167                 }
168         else
169                 {
170                 ret->type=V_ASN1_INTEGER;
171                 if ((*p == 0) && (len != 1))
172                         {
173                         p++;
174                         len--;
175                         }
176                 memcpy(s,p,(int)len);
177                 p+=len;
178                 }
179
180         if (ret->data != NULL) Free((char *)ret->data);
181         ret->data=s;
182         ret->length=(int)len;
183         if (a != NULL) (*a)=ret;
184         *pp=p;
185         return(ret);
186 err:
187         ASN1err(ASN1_F_D2I_ASN1_INTEGER,i);
188         if ((ret != NULL) && ((a == NULL) || (*a != ret)))
189                 ASN1_INTEGER_free(ret);
190         return(NULL);
191         }
192
193 int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
194         {
195         int i,j,k;
196         unsigned char buf[sizeof(long)+1];
197         long d;
198
199         a->type=V_ASN1_INTEGER;
200         if (a->length < (sizeof(long)+1))
201                 {
202                 if (a->data != NULL)
203                         Free((char *)a->data);
204                 if ((a->data=(unsigned char *)Malloc(sizeof(long)+1)) != NULL)
205                         memset((char *)a->data,0,sizeof(long)+1);
206                 }
207         if (a->data == NULL)
208                 {
209                 ASN1err(ASN1_F_ASN1_INTEGER_SET,ERR_R_MALLOC_FAILURE);
210                 return(0);
211                 }
212         d=v;
213         if (d < 0)
214                 {
215                 d= -d;
216                 a->type=V_ASN1_NEG_INTEGER;
217                 }
218
219         for (i=0; i<sizeof(long); i++)
220                 {
221                 if (d == 0) break;
222                 buf[i]=(int)d&0xff;
223                 d>>=8;
224                 }
225         j=0;
226         if (v < 0) a->data[j++]=0;
227         for (k=i-1; k >=0; k--)
228                 a->data[j++]=buf[k];
229         a->length=j;
230         return(1);
231         }
232
233 long ASN1_INTEGER_get(ASN1_INTEGER *a)
234         {
235         int neg=0,i;
236         long r=0;
237
238         if (a == NULL) return(0L);
239         i=a->type;
240         if (i == V_ASN1_NEG_INTEGER)
241                 neg=1;
242         else if (i != V_ASN1_INTEGER)
243                 return(0);
244         
245         if (a->length > sizeof(long))
246                 {
247                 /* hmm... a bit ugly */
248                 return(0xffffffffL);
249                 }
250         if (a->data == NULL)
251                 return(0);
252
253         for (i=0; i<a->length; i++)
254                 {
255                 r<<=8;
256                 r|=(unsigned char)a->data[i];
257                 }
258         if (neg) r= -r;
259         return(r);
260         }
261
262 ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *bn, ASN1_INTEGER *ai)
263         {
264         ASN1_INTEGER *ret;
265         int len,j;
266
267         if (ai == NULL)
268                 ret=ASN1_INTEGER_new();
269         else
270                 ret=ai;
271         if (ret == NULL)
272                 {
273                 ASN1err(ASN1_F_BN_TO_ASN1_INTEGER,ERR_R_NESTED_ASN1_ERROR);
274                 goto err;
275                 }
276         ret->type=V_ASN1_INTEGER;
277         j=BN_num_bits(bn);
278         len=((j == 0)?0:((j/8)+1));
279         ret->data=(unsigned char *)Malloc(len+4);
280         ret->length=BN_bn2bin(bn,ret->data);
281         return(ret);
282 err:
283         if (ret != ai) ASN1_INTEGER_free(ret);
284         return(NULL);
285         }
286
287 BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *ai, BIGNUM *bn)
288         {
289         BIGNUM *ret;
290
291         if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
292                 ASN1err(ASN1_F_ASN1_INTEGER_TO_BN,ASN1_R_BN_LIB);
293         return(ret);
294         }