Line data Source code
1 : /* x_long.c */
2 : /*
3 : * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4 : * 2000.
5 : */
6 : /* ====================================================================
7 : * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : *
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : *
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in
18 : * the documentation and/or other materials provided with the
19 : * distribution.
20 : *
21 : * 3. All advertising materials mentioning features or use of this
22 : * software must display the following acknowledgment:
23 : * "This product includes software developed by the OpenSSL Project
24 : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 : *
26 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 : * endorse or promote products derived from this software without
28 : * prior written permission. For written permission, please contact
29 : * licensing@OpenSSL.org.
30 : *
31 : * 5. Products derived from this software may not be called "OpenSSL"
32 : * nor may "OpenSSL" appear in their names without prior written
33 : * permission of the OpenSSL Project.
34 : *
35 : * 6. Redistributions of any form whatsoever must retain the following
36 : * acknowledgment:
37 : * "This product includes software developed by the OpenSSL Project
38 : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 : *
40 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 : * OF THE POSSIBILITY OF SUCH DAMAGE.
52 : * ====================================================================
53 : *
54 : * This product includes cryptographic software written by Eric Young
55 : * (eay@cryptsoft.com). This product includes software written by Tim
56 : * Hudson (tjh@cryptsoft.com).
57 : *
58 : */
59 :
60 : #include <stdio.h>
61 : #include "cryptlib.h"
62 : #include <openssl/asn1t.h>
63 : #include <openssl/bn.h>
64 :
65 : /*
66 : * Custom primitive type for long handling. This converts between an
67 : * ASN1_INTEGER and a long directly.
68 : */
69 :
70 : static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
71 : static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
72 :
73 : static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
74 : const ASN1_ITEM *it);
75 : static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
76 : int utype, char *free_cont, const ASN1_ITEM *it);
77 : static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
78 : int indent, const ASN1_PCTX *pctx);
79 :
80 : static ASN1_PRIMITIVE_FUNCS long_pf = {
81 : NULL, 0,
82 : long_new,
83 : long_free,
84 : long_free, /* Clear should set to initial value */
85 : long_c2i,
86 : long_i2c,
87 : long_print
88 : };
89 :
90 : ASN1_ITEM_start(LONG)
91 : ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
92 : ASN1_ITEM_end(LONG)
93 :
94 : ASN1_ITEM_start(ZLONG)
95 : ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
96 : ASN1_ITEM_end(ZLONG)
97 :
98 0 : static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
99 : {
100 0 : *(long *)pval = it->size;
101 0 : return 1;
102 : }
103 :
104 0 : static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
105 : {
106 0 : *(long *)pval = it->size;
107 0 : }
108 :
109 0 : static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
110 : const ASN1_ITEM *it)
111 : {
112 : long ltmp;
113 : unsigned long utmp;
114 : int clen, pad, i;
115 : /* this exists to bypass broken gcc optimization */
116 : char *cp = (char *)pval;
117 :
118 : /* use memcpy, because we may not be long aligned */
119 : memcpy(<mp, cp, sizeof(long));
120 :
121 0 : if (ltmp == it->size)
122 : return -1;
123 : /*
124 : * Convert the long to positive: we subtract one if negative so we can
125 : * cleanly handle the padding if only the MSB of the leading octet is
126 : * set.
127 : */
128 0 : if (ltmp < 0)
129 0 : utmp = -ltmp - 1;
130 : else
131 0 : utmp = ltmp;
132 0 : clen = BN_num_bits_word(utmp);
133 : /* If MSB of leading octet set we need to pad */
134 0 : if (!(clen & 0x7))
135 : pad = 1;
136 : else
137 : pad = 0;
138 :
139 : /* Convert number of bits to number of octets */
140 0 : clen = (clen + 7) >> 3;
141 :
142 0 : if (cont) {
143 0 : if (pad)
144 0 : *cont++ = (ltmp < 0) ? 0xff : 0;
145 0 : for (i = clen - 1; i >= 0; i--) {
146 0 : cont[i] = (unsigned char)(utmp & 0xff);
147 0 : if (ltmp < 0)
148 0 : cont[i] ^= 0xff;
149 0 : utmp >>= 8;
150 : }
151 : }
152 0 : return clen + pad;
153 : }
154 :
155 450 : static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
156 : int utype, char *free_cont, const ASN1_ITEM *it)
157 : {
158 : int neg, i;
159 : long ltmp;
160 : unsigned long utmp = 0;
161 : char *cp = (char *)pval;
162 450 : if (len > (int)sizeof(long)) {
163 0 : ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
164 0 : return 0;
165 : }
166 : /* Is it negative? */
167 450 : if (len && (cont[0] & 0x80))
168 : neg = 1;
169 : else
170 : neg = 0;
171 : utmp = 0;
172 900 : for (i = 0; i < len; i++) {
173 450 : utmp <<= 8;
174 450 : if (neg)
175 0 : utmp |= cont[i] ^ 0xff;
176 : else
177 450 : utmp |= cont[i];
178 : }
179 450 : ltmp = (long)utmp;
180 450 : if (neg) {
181 0 : ltmp++;
182 0 : ltmp = -ltmp;
183 : }
184 450 : if (ltmp == it->size) {
185 0 : ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
186 0 : return 0;
187 : }
188 : memcpy(cp, <mp, sizeof(long));
189 450 : return 1;
190 : }
191 :
192 0 : static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
193 : int indent, const ASN1_PCTX *pctx)
194 : {
195 0 : return BIO_printf(out, "%ld\n", *(long *)pval);
196 : }
|