d180a3bb3ac08490cbbebaed3df96e81183b3a38
[openssl.git] / crypto / asn1 / x_int64.c
1 /*
2  * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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/asn1t.h"
13 #include "internal/numbers.h"
14 #include <openssl/bn.h>
15 #include "asn1_locl.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
29 static int uint64_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
30 {
31     *(uint64_t *)pval = 0;
32     return 1;
33 }
34
35 static void uint64_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
36 {
37     *(uint64_t *)pval = 0;
38 }
39
40 static int uint64_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
41                     const ASN1_ITEM *it)
42 {
43     uint64_t utmp;
44     int neg = 0;
45     /* this exists to bypass broken gcc optimization */
46     char *cp = (char *)pval;
47
48     /* use memcpy, because we may not be uint64_t aligned */
49     memcpy(&utmp, cp, sizeof(utmp));
50
51     if ((it->size & INTxx_FLAG_ZERO_DEFAULT) == INTxx_FLAG_ZERO_DEFAULT
52         && utmp == 0)
53         return -1;
54     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
55         && (int64_t)utmp < 0)
56         neg = 1;
57
58     return i2c_uint64_int(cont, utmp, neg);
59 }
60
61 static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
62                     int utype, char *free_cont, const ASN1_ITEM *it)
63 {
64     uint64_t utmp = 0;
65     char *cp = (char *)pval;
66     int neg = 0;
67
68     if (!c2i_uint64_int(&utmp, &neg, &cont, len))
69         return 0;
70     if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) {
71         ASN1err(ASN1_F_UINT64_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
72         return 0;
73     }
74     memcpy(cp, &utmp, sizeof(utmp));
75     return 1;
76 }
77
78 static int uint64_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
79                         int indent, const ASN1_PCTX *pctx)
80 {
81     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
82         return BIO_printf(out, "%jd\n", *(int64_t *)pval);
83     return BIO_printf(out, "%ju\n", *(uint64_t *)pval);
84 }
85
86 /* 32-bit variants */
87
88 static int uint32_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
89 {
90     *(uint32_t *)pval = 0;
91     return 1;
92 }
93
94 static void uint32_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
95 {
96     *(uint32_t *)pval = 0;
97 }
98
99 static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
100                     const ASN1_ITEM *it)
101 {
102     uint32_t utmp;
103     int neg = 0;
104     /* this exists to bypass broken gcc optimization */
105     char *cp = (char *)pval;
106
107     /* use memcpy, because we may not be uint32_t aligned */
108     memcpy(&utmp, cp, sizeof(utmp));
109
110     if ((it->size & INTxx_FLAG_ZERO_DEFAULT) == INTxx_FLAG_ZERO_DEFAULT
111         && utmp == 0)
112         return -1;
113     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
114         && (int32_t)utmp < 0)
115         neg = 1;
116
117     return i2c_uint64_int(cont, (uint64_t)utmp, neg);
118 }
119
120 static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
121                     int utype, char *free_cont, const ASN1_ITEM *it)
122 {
123     uint64_t utmp = 0;
124     uint32_t utmp2 = 0;
125     char *cp = (char *)pval;
126     int neg = 0;
127
128     if (!c2i_uint64_int(&utmp, &neg, &cont, len))
129         return 0;
130     if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) {
131         ASN1err(ASN1_F_UINT32_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
132         return 0;
133     }
134     utmp2 = (uint32_t)utmp;
135     if (utmp != utmp2
136         || ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
137             && !neg && utmp2 > INT32_MAX)) {
138         ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_LARGE);
139         return 0;
140     }
141     memcpy(cp, &utmp2, sizeof(utmp2));
142     return 1;
143 }
144
145 static int uint32_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
146                         int indent, const ASN1_PCTX *pctx)
147 {
148     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
149         return BIO_printf(out, "%d\n", *(int32_t *)pval);
150     return BIO_printf(out, "%u\n", *(uint32_t *)pval);
151 }
152
153
154 /* Define the primitives themselves */
155
156 static ASN1_PRIMITIVE_FUNCS uint32_pf = {
157     NULL, 0,
158     uint32_new,
159     uint32_free,
160     uint32_free,                  /* Clear should set to initial value */
161     uint32_c2i,
162     uint32_i2c,
163     uint32_print
164 };
165
166 static ASN1_PRIMITIVE_FUNCS uint64_pf = {
167     NULL, 0,
168     uint64_new,
169     uint64_free,
170     uint64_free,                  /* Clear should set to initial value */
171     uint64_c2i,
172     uint64_i2c,
173     uint64_print
174 };
175
176 ASN1_ITEM_start(INT32)
177     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
178     INTxx_FLAG_SIGNED, "INT32"
179 ASN1_ITEM_end(INT32)
180
181 ASN1_ITEM_start(UINT32)
182     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, 0, "UINT32"
183 ASN1_ITEM_end(UINT32)
184
185 ASN1_ITEM_start(INT64)
186     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
187     INTxx_FLAG_SIGNED, "INT64"
188 ASN1_ITEM_end(INT64)
189
190 ASN1_ITEM_start(UINT64)
191     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, 0, "UINT64"
192 ASN1_ITEM_end(UINT64)
193
194 ASN1_ITEM_start(ZINT32)
195     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
196     INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT32"
197 ASN1_ITEM_end(ZINT32)
198
199 ASN1_ITEM_start(ZUINT32)
200     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
201     INTxx_FLAG_ZERO_DEFAULT, "ZUINT32"
202 ASN1_ITEM_end(ZUINT32)
203
204 ASN1_ITEM_start(ZINT64)
205     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
206     INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT64"
207 ASN1_ITEM_end(ZINT64)
208
209 ASN1_ITEM_start(ZUINT64)
210     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
211     INTxx_FLAG_ZERO_DEFAULT, "ZUINT64"
212 ASN1_ITEM_end(ZUINT64)
213