summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2022-07-02 18:14:35 +0000
committerjsing <>2022-07-02 18:14:35 +0000
commit963c47667fc47c301ad45580a2b27b25cf2a3c6d (patch)
tree6a96b8dcfddfc28019de4d09fe4a3134a64141df /src
parent7ef5c3d971675518039445a2bb528972218e01b2 (diff)
downloadopenbsd-963c47667fc47c301ad45580a2b27b25cf2a3c6d.tar.gz
openbsd-963c47667fc47c301ad45580a2b27b25cf2a3c6d.tar.bz2
openbsd-963c47667fc47c301ad45580a2b27b25cf2a3c6d.zip
Use ASN1_INTEGER to parse/build (Z)LONG_it
Rather than having yet another (broken) ASN.1 INTEGER content builder and parser, use {c2i,i2c}_ASN1_INTEGER(). ok beck@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/asn1/x_long.c136
1 files changed, 67 insertions, 69 deletions
diff --git a/src/lib/libcrypto/asn1/x_long.c b/src/lib/libcrypto/asn1/x_long.c
index b51ea6f214..543c56a5b2 100644
--- a/src/lib/libcrypto/asn1/x_long.c
+++ b/src/lib/libcrypto/asn1/x_long.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x_long.c,v 1.17 2022/06/26 13:10:15 jsing Exp $ */ 1/* $OpenBSD: x_long.c,v 1.18 2022/07/02 18:14:35 jsing Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2000. 3 * project 2000.
4 */ 4 */
@@ -56,13 +56,15 @@
56 * 56 *
57 */ 57 */
58 58
59#include <stdio.h> 59#include <limits.h>
60#include <string.h> 60#include <string.h>
61 61
62#include <openssl/asn1t.h> 62#include <openssl/asn1t.h>
63#include <openssl/bn.h> 63#include <openssl/bn.h>
64#include <openssl/err.h> 64#include <openssl/err.h>
65 65
66#include "asn1_locl.h"
67
66/* 68/*
67 * Custom primitive type for long handling. This converts between an 69 * Custom primitive type for long handling. This converts between an
68 * ASN1_INTEGER and a long directly. 70 * ASN1_INTEGER and a long directly.
@@ -72,10 +74,10 @@ static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
72static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it); 74static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
73static void long_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); 75static void long_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
74 76
75static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, 77static int long_i2c(ASN1_VALUE **pval, unsigned char *content, int *putype,
76 const ASN1_ITEM *it); 78 const ASN1_ITEM *it);
77static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, 79static int long_c2i(ASN1_VALUE **pval, const unsigned char *content, int len,
78 int utype, char *free_cont, const ASN1_ITEM *it); 80 int utype, char *free_content, const ASN1_ITEM *it);
79static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, 81static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
80 int indent, const ASN1_PCTX *pctx); 82 int indent, const ASN1_PCTX *pctx);
81 83
@@ -144,86 +146,82 @@ long_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
144} 146}
145 147
146static int 148static int
147long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, 149long_i2c(ASN1_VALUE **pval, unsigned char *content, int *putype,
148 const ASN1_ITEM *it) 150 const ASN1_ITEM *it)
149{ 151{
150 long ltmp; 152 ASN1_INTEGER *aint;
151 unsigned long utmp; 153 uint8_t **pp = NULL;
152 int clen, pad, i; 154 long val;
155 int ret = 0;
153 156
154 long_get(pval, &ltmp); 157 long_get(pval, &val);
155 158
156 if (ltmp == it->size) 159 /*
157 return -1; 160 * The zero value for this type (stored in the overloaded it->size
158 /* Convert the long to positive: we subtract one if negative so 161 * field) is considered to be invalid.
159 * we can cleanly handle the padding if only the MSB of the leading
160 * octet is set.
161 */ 162 */
162 if (ltmp < 0) 163 if (val == it->size)
163 utmp = -(ltmp + 1); 164 return -1;
164 else 165
165 utmp = ltmp; 166 if ((aint = ASN1_INTEGER_new()) == NULL)
166 clen = BN_num_bits_word(utmp); 167 goto err;
167 /* If MSB of leading octet set we need to pad */ 168 if (!ASN1_INTEGER_set_int64(aint, (int64_t)val))
168 if (!(clen & 0x7)) 169 goto err;
169 pad = 1; 170 if (content != NULL)
170 else 171 pp = &content;
171 pad = 0; 172 ret = i2c_ASN1_INTEGER(aint, pp);
172 173
173 /* Convert number of bits to number of octets */ 174 err:
174 clen = (clen + 7) >> 3; 175 ASN1_INTEGER_free(aint);
175 176
176 if (cont) { 177 return ret;
177 if (pad)
178 *cont++ = (ltmp < 0) ? 0xff : 0;
179 for (i = clen - 1; i >= 0; i--) {
180 cont[i] = (unsigned char)(utmp & 0xff);
181 if (ltmp < 0)
182 cont[i] ^= 0xff;
183 utmp >>= 8;
184 }
185 }
186 return clen + pad;
187} 178}
188 179
189static int 180static int
190long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, 181long_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype,
191 char *free_cont, const ASN1_ITEM *it) 182 char *free_content, const ASN1_ITEM *it)
192{ 183{
193 int neg, i; 184 ASN1_INTEGER *aint = NULL;
194 long ltmp; 185 const uint8_t **pp = NULL;
195 unsigned long utmp = 0; 186 int64_t val = 0;
187 int ret = 0;
188
189 /*
190 * The original long_i2c() mishandled 0 values and encoded them as
191 * content with zero length, rather than a single zero byte. Permit
192 * zero length content here for backwards compatibility.
193 */
194 if (len != 0) {
195 if (content != NULL)
196 pp = &content;
197 if (!c2i_ASN1_INTEGER(&aint, pp, len))
198 goto err;
199 if (!ASN1_INTEGER_get_int64(&val, aint))
200 goto err;
201 }
196 202
197 if (len > (int)sizeof(long)) { 203 if (val < LONG_MIN || val > LONG_MAX) {
198 ASN1error(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); 204 ASN1error(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
199 return 0; 205 goto err;
200 }
201 /* Is it negative? */
202 if (len && (cont[0] & 0x80))
203 neg = 1;
204 else
205 neg = 0;
206 utmp = 0;
207 for (i = 0; i < len; i++) {
208 utmp <<= 8;
209 if (neg)
210 utmp |= cont[i] ^ 0xff;
211 else
212 utmp |= cont[i];
213 } 206 }
214 ltmp = (long)utmp; 207
215 if (neg) { 208 /*
216 ltmp = -ltmp; 209 * The zero value for this type (stored in the overloaded it->size
217 ltmp--; 210 * field) is considered to be invalid.
218 } 211 */
219 if (ltmp == it->size) { 212 if (val == (int64_t)it->size) {
220 ASN1error(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); 213 ASN1error(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
221 return 0; 214 goto err;
222 } 215 }
223 216
224 long_set(pval, ltmp); 217 long_set(pval, (long)val);
225 218
226 return 1; 219 ret = 1;
220
221 err:
222 ASN1_INTEGER_free(aint);
223
224 return ret;
227} 225}
228 226
229static int 227static int