diff options
Diffstat (limited to 'lib/asn1/der_put.c')
| -rw-r--r-- | lib/asn1/der_put.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/lib/asn1/der_put.c b/lib/asn1/der_put.c index 843d09f5cdc1..98c2c8a2cebb 100644 --- a/lib/asn1/der_put.c +++ b/lib/asn1/der_put.c @@ -313,7 +313,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; } @@ -341,19 +342,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); |
