33e406169945f75b2178c7f216902d663a968ed9
[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/numbers.h"
13 #include <openssl/asn1t.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     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
75             && !neg && utmp > INT64_MAX) {
76         ASN1err(ASN1_F_UINT64_C2I, ASN1_R_TOO_LARGE);
77         return 0;
78     }
79     memcpy(cp, &utmp, sizeof(utmp));
80     return 1;
81 }
82
83 static int uint64_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
84                         int indent, const ASN1_PCTX *pctx)
85 {
86     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
87         return BIO_printf(out, "%jd\n", *(int64_t *)pval);
88     return BIO_printf(out, "%ju\n", *(uint64_t *)pval);
89 }
90
91 /* 32-bit variants */
92
93 static int uint32_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
94 {
95     *(uint32_t *)pval = 0;
96     return 1;
97 }
98
99 static void uint32_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
100 {
101     *(uint32_t *)pval = 0;
102 }
103
104 static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
105                     const ASN1_ITEM *it)
106 {
107     uint32_t utmp;
108     int neg = 0;
109     /* this exists to bypass broken gcc optimization */
110     char *cp = (char *)pval;
111
112     /* use memcpy, because we may not be uint32_t aligned */
113     memcpy(&utmp, cp, sizeof(utmp));
114
115     if ((it->size & INTxx_FLAG_ZERO_DEFAULT) == INTxx_FLAG_ZERO_DEFAULT
116         && utmp == 0)
117         return -1;
118     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
119         && (int32_t)utmp < 0)
120         neg = 1;
121
122     return i2c_uint64_int(cont, (uint64_t)utmp, neg);
123 }
124
125 static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
126                     int utype, char *free_cont, const ASN1_ITEM *it)
127 {
128     uint64_t utmp = 0;
129     uint32_t utmp2 = 0;
130     char *cp = (char *)pval;
131     int neg = 0;
132
133     if (!c2i_uint64_int(&utmp, &neg, &cont, len))
134         return 0;
135     if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) {
136         ASN1err(ASN1_F_UINT32_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
137         return 0;
138     }
139     utmp2 = (uint32_t)utmp;
140     if (utmp != utmp2
141         || ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
142             && !neg && utmp2 > INT32_MAX)) {
143         ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_LARGE);
144         return 0;
145     }
146     memcpy(cp, &utmp2, sizeof(utmp2));
147     return 1;
148 }
149
150 static int uint32_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
151                         int indent, const ASN1_PCTX *pctx)
152 {
153     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
154         return BIO_printf(out, "%d\n", *(int32_t *)pval);
155     return BIO_printf(out, "%u\n", *(uint32_t *)pval);
156 }
157
158
159 /* Define the primitives themselves */
160
161 static ASN1_PRIMITIVE_FUNCS uint32_pf = {
162     NULL, 0,
163     uint32_new,
164     uint32_free,
165     uint32_free,                  /* Clear should set to initial value */
166     uint32_c2i,
167     uint32_i2c,
168     uint32_print
169 };
170
171 static ASN1_PRIMITIVE_FUNCS uint64_pf = {
172     NULL, 0,
173     uint64_new,
174     uint64_free,
175     uint64_free,                  /* Clear should set to initial value */
176     uint64_c2i,
177     uint64_i2c,
178     uint64_print
179 };
180
181 ASN1_ITEM_start(INT32)
182     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
183     INTxx_FLAG_SIGNED, "INT32"
184 ASN1_ITEM_end(INT32)
185
186 ASN1_ITEM_start(UINT32)
187     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, 0, "UINT32"
188 ASN1_ITEM_end(UINT32)
189
190 ASN1_ITEM_start(INT64)
191     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
192     INTxx_FLAG_SIGNED, "INT64"
193 ASN1_ITEM_end(INT64)
194
195 ASN1_ITEM_start(UINT64)
196     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, 0, "UINT64"
197 ASN1_ITEM_end(UINT64)
198
199 ASN1_ITEM_start(ZINT32)
200     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
201     INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT32"
202 ASN1_ITEM_end(ZINT32)
203
204 ASN1_ITEM_start(ZUINT32)
205     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf,
206     INTxx_FLAG_ZERO_DEFAULT, "ZUINT32"
207 ASN1_ITEM_end(ZUINT32)
208
209 ASN1_ITEM_start(ZINT64)
210     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
211     INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT64"
212 ASN1_ITEM_end(ZINT64)
213
214 ASN1_ITEM_start(ZUINT64)
215     ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf,
216     INTxx_FLAG_ZERO_DEFAULT, "ZUINT64"
217 ASN1_ITEM_end(ZUINT64)
218