diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/asn1/x_long.c | 136 |
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); | |||
| 72 | static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it); | 74 | static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it); |
| 73 | static void long_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); | 75 | static void long_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); |
| 74 | 76 | ||
| 75 | static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, | 77 | static int long_i2c(ASN1_VALUE **pval, unsigned char *content, int *putype, |
| 76 | const ASN1_ITEM *it); | 78 | const ASN1_ITEM *it); |
| 77 | static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, | 79 | static 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); |
| 79 | static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, | 81 | static 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 | ||
| 146 | static int | 148 | static int |
| 147 | long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, | 149 | long_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, <mp); | 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 | ||
| 189 | static int | 180 | static int |
| 190 | long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, | 181 | long_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 | ||
| 229 | static int | 227 | static int |
