• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include "internal/numbers.h"
13 #include <openssl/asn1t.h>
14 #include <openssl/bn.h>
15 #include "asn1_local.h"
16 
17 /*
18  * Custom primitive types for handling int32_t, int64_t, uint32_t, uint64_t.
19  * This converts between an ASN1_INTEGER and those types directly.
20  * This is preferred to using the LONG / ZLONG primitives.
21  */
22 
23 /*
24  * We abuse the ASN1_ITEM fields |size| as a flags field
25  */
26 #define INTxx_FLAG_ZERO_DEFAULT (1<<0)
27 #define INTxx_FLAG_SIGNED       (1<<1)
28 
uint64_new(ASN1_VALUE ** pval,const ASN1_ITEM * it)29 static int uint64_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
30 {
31     if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint64_t))) == NULL) {
32         ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
33         return 0;
34     }
35     return 1;
36 }
37 
uint64_free(ASN1_VALUE ** pval,const ASN1_ITEM * it)38 static void uint64_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
39 {
40     OPENSSL_free(*pval);
41     *pval = NULL;
42 }
43 
uint64_clear(ASN1_VALUE ** pval,const ASN1_ITEM * it)44 static void uint64_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
45 {
46     **(uint64_t **)pval = 0;
47 }
48 
uint64_i2c(const ASN1_VALUE ** pval,unsigned char * cont,int * putype,const ASN1_ITEM * it)49 static int uint64_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
50                       const ASN1_ITEM *it)
51 {
52     uint64_t utmp;
53     int neg = 0;
54     /* this exists to bypass broken gcc optimization */
55     char *cp = (char *)*pval;
56 
57     /* use memcpy, because we may not be uint64_t aligned */
58     memcpy(&utmp, cp, sizeof(utmp));
59 
60     if ((it->size & INTxx_FLAG_ZERO_DEFAULT) == INTxx_FLAG_ZERO_DEFAULT
61         && utmp == 0)
62         return -1;
63     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
64         && (int64_t)utmp < 0) {
65         /* ossl_i2c_uint64_int() assumes positive values */
66         utmp = 0 - utmp;
67         neg = 1;
68     }
69 
70     return ossl_i2c_uint64_int(cont, utmp, neg);
71 }
72 
uint64_c2i(ASN1_VALUE ** pval,const unsigned char * cont,int len,int utype,char * free_cont,const ASN1_ITEM * it)73 static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
74                       int utype, char *free_cont, const ASN1_ITEM *it)
75 {
76     uint64_t utmp = 0;
77     char *cp;
78     int neg = 0;
79 
80     if (*pval == NULL && !uint64_new(pval, it))
81         return 0;
82 
83     cp = (char *)*pval;
84 
85     /*
86      * Strictly speaking, zero length is malformed.  However, long_c2i
87      * (x_long.c) encodes 0 as a zero length INTEGER (wrongly, of course),
88      * so for the sake of backward compatibility, we still decode zero
89      * length INTEGERs as the number zero.
90      */
91     if (len == 0)
92         goto long_compat;
93 
94     if (!ossl_c2i_uint64_int(&utmp, &neg, &cont, len))
95         return 0;
96     if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) {
97         ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
98         return 0;
99     }
100     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
101             && !neg && utmp > INT64_MAX) {
102         ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
103         return 0;
104     }
105     if (neg)
106         /* ossl_c2i_uint64_int() returns positive values */
107         utmp = 0 - utmp;
108 
109  long_compat:
110     memcpy(cp, &utmp, sizeof(utmp));
111     return 1;
112 }
113 
uint64_print(BIO * out,const ASN1_VALUE ** pval,const ASN1_ITEM * it,int indent,const ASN1_PCTX * pctx)114 static int uint64_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
115                         int indent, const ASN1_PCTX *pctx)
116 {
117     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
118         return BIO_printf(out, "%jd\n", **(int64_t **)pval);
119     return BIO_printf(out, "%ju\n", **(uint64_t **)pval);
120 }
121 
122 /* 32-bit variants */
123 
uint32_new(ASN1_VALUE ** pval,const ASN1_ITEM * it)124 static int uint32_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
125 {
126     if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint32_t))) == NULL) {
127         ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
128         return 0;
129     }
130     return 1;
131 }
132 
uint32_free(ASN1_VALUE ** pval,const ASN1_ITEM * it)133 static void uint32_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
134 {
135     OPENSSL_free(*pval);
136     *pval = NULL;
137 }
138 
uint32_clear(ASN1_VALUE ** pval,const ASN1_ITEM * it)139 static void uint32_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
140 {
141     **(uint32_t **)pval = 0;
142 }
143 
uint32_i2c(const ASN1_VALUE ** pval,unsigned char * cont,int * putype,const ASN1_ITEM * it)144 static int uint32_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
145                       const ASN1_ITEM *it)
146 {
147     uint32_t utmp;
148     int neg = 0;
149     /* this exists to bypass broken gcc optimization */
150     char *cp = (char *)*pval;
151 
152     /* use memcpy, because we may not be uint32_t aligned */
153     memcpy(&utmp, cp, sizeof(utmp));
154 
155     if ((it->size & INTxx_FLAG_ZERO_DEFAULT) == INTxx_FLAG_ZERO_DEFAULT
156         && utmp == 0)
157         return -1;
158     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
159         && (int32_t)utmp < 0) {
160         /* ossl_i2c_uint64_int() assumes positive values */
161         utmp = 0 - utmp;
162         neg = 1;
163     }
164 
165     return ossl_i2c_uint64_int(cont, (uint64_t)utmp, neg);
166 }
167 
168 /*
169  * Absolute value of INT32_MIN: we can't just use -INT32_MIN as it produces
170  * overflow warnings.
171  */
172 
173 #define ABS_INT32_MIN ((uint32_t)INT32_MAX + 1)
174 
uint32_c2i(ASN1_VALUE ** pval,const unsigned char * cont,int len,int utype,char * free_cont,const ASN1_ITEM * it)175 static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
176                       int utype, char *free_cont, const ASN1_ITEM *it)
177 {
178     uint64_t utmp = 0;
179     uint32_t utmp2 = 0;
180     char *cp;
181     int neg = 0;
182 
183     if (*pval == NULL && !uint64_new(pval, it))
184         return 0;
185 
186     cp = (char *)*pval;
187 
188     /*
189      * Strictly speaking, zero length is malformed.  However, long_c2i
190      * (x_long.c) encodes 0 as a zero length INTEGER (wrongly, of course),
191      * so for the sake of backward compatibility, we still decode zero
192      * length INTEGERs as the number zero.
193      */
194     if (len == 0)
195         goto long_compat;
196 
197     if (!ossl_c2i_uint64_int(&utmp, &neg, &cont, len))
198         return 0;
199     if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) {
200         ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
201         return 0;
202     }
203     if (neg) {
204         if (utmp > ABS_INT32_MIN) {
205             ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
206             return 0;
207         }
208         utmp = 0 - utmp;
209     } else {
210         if (((it->size & INTxx_FLAG_SIGNED) != 0 && utmp > INT32_MAX)
211             || ((it->size & INTxx_FLAG_SIGNED) == 0 && utmp > UINT32_MAX)) {
212             ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
213             return 0;
214         }
215     }
216 
217  long_compat:
218     utmp2 = (uint32_t)utmp;
219     memcpy(cp, &utmp2, sizeof(utmp2));
220     return 1;
221 }
222 
uint32_print(BIO * out,const ASN1_VALUE ** pval,const ASN1_ITEM * it,int indent,const ASN1_PCTX * pctx)223 static int uint32_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
224                         int indent, const ASN1_PCTX *pctx)
225 {
226     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
227         return BIO_printf(out, "%d\n", **(int32_t **)pval);
228     return BIO_printf(out, "%u\n", **(uint32_t **)pval);
229 }
230 
231 
232 /* Define the primitives themselves */
233 
234 static ASN1_PRIMITIVE_FUNCS uint32_pf = {
235     NULL, 0,
236     uint32_new,
237     uint32_free,
238     uint32_clear,
239     uint32_c2i,
240     uint32_i2c,
241     uint32_print
242 };
243 
244 static ASN1_PRIMITIVE_FUNCS uint64_pf = {
245     NULL, 0,
246     uint64_new,
247     uint64_free,
248     uint64_clear,
249     uint64_c2i,
250     uint64_i2c,
251     uint64_print
252 };
253 
254 ASN1_ITEM_start(INT32)
255     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
256     INTxx_FLAG_SIGNED, "INT32"
257 ASN1_ITEM_end(INT32)
258 
259 ASN1_ITEM_start(UINT32)
260     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, 0, "UINT32"
261 ASN1_ITEM_end(UINT32)
262 
263 ASN1_ITEM_start(INT64)
264     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
265     INTxx_FLAG_SIGNED, "INT64"
266 ASN1_ITEM_end(INT64)
267 
268 ASN1_ITEM_start(UINT64)
269     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, 0, "UINT64"
270 ASN1_ITEM_end(UINT64)
271 
272 ASN1_ITEM_start(ZINT32)
273     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
274     INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT32"
275 ASN1_ITEM_end(ZINT32)
276 
277 ASN1_ITEM_start(ZUINT32)
278     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
279     INTxx_FLAG_ZERO_DEFAULT, "ZUINT32"
280 ASN1_ITEM_end(ZUINT32)
281 
282 ASN1_ITEM_start(ZINT64)
283     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
284     INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT64"
285 ASN1_ITEM_end(ZINT64)
286 
287 ASN1_ITEM_start(ZUINT64)
288     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
289     INTxx_FLAG_ZERO_DEFAULT, "ZUINT64"
290 ASN1_ITEM_end(ZUINT64)
291 
292