asn1: Fix UB and incorrect codec for unconstrained INTEGER values of -1

This commit is contained in:
Nicolas Williams
2022-10-26 01:53:10 -05:00
parent 476d216f89
commit e4311f3a82
5 changed files with 206 additions and 55 deletions

View File

@@ -343,7 +343,8 @@ der_put_octet_string (unsigned char *p, size_t len,
if (len < data->length)
return ASN1_OVERFLOW;
p -= data->length;
memcpy (p+1, data->data, data->length);
if (data->length)
memcpy(p+1, data->data, data->length);
*size = data->length;
return 0;
}
@@ -378,19 +379,30 @@ der_put_heim_integer (unsigned char *p, size_t len,
if (data->negative) {
ssize_t i;
int carry;
for (i = data->length - 1, carry = 1; i >= 0; i--) {
*p = buf[i] ^ 0xff;
if (carry)
carry = !++*p;
p--;
}
if (p[1] < 128) {
if (len < 1)
return ASN1_OVERFLOW;
*p-- = 0xff;
len--;
hibitset = 1;
}
/*
* We represent the parsed integer as a positive value with a
* negativity flag. But we need to put it on the wire as the shortest
* twos-complement byte sequence possible. So we're going to negate
* the number as go.
*/
if (data->length == 1 && *(unsigned char *)data->data == 1) {
*(p--) = 0xff;
} else {
for (i = data->length - 1, carry = 1; i >= 0; i--) {
*p = buf[i] ^ 0xff;
if (carry)
carry = !++*p;
p--;
}
if (p[1] < 128) {
if (len < 1)
return ASN1_OVERFLOW;
*p-- = 0xff;
len--;
hibitset = 1;
}
}
} else {
p -= data->length;
memcpy(p + 1, buf, data->length);