Add ASN1_INTEGET_set_uint64. Change-Id: I3298875a376c98cbb60deb8c99b9548c84b014df Reviewed-on: https://boringssl-review.googlesource.com/24484 Commit-Queue: Adam Langley <agl@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org> Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c index 8a4edd6..b53c00b 100644 --- a/crypto/asn1/a_int.c +++ b/crypto/asn1/a_int.c
@@ -383,6 +383,35 @@ return (1); } +int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v) +{ + uint8_t *const newdata = OPENSSL_malloc(sizeof(uint64_t)); + if (newdata == NULL) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); + return 0; + } + + OPENSSL_free(out->data); + out->data = newdata; + v = CRYPTO_bswap8(v); + memcpy(out->data, &v, sizeof(v)); + + out->type = V_ASN1_INTEGER; + + size_t leading_zeros; + for (leading_zeros = 0; leading_zeros < sizeof(uint64_t) - 1; + leading_zeros++) { + if (out->data[leading_zeros] != 0) { + break; + } + } + + out->length = sizeof(uint64_t) - leading_zeros; + OPENSSL_memmove(out->data, out->data + leading_zeros, out->length); + + return 1; +} + long ASN1_INTEGER_get(const ASN1_INTEGER *a) { int neg = 0, i;
diff --git a/crypto/asn1/asn1_test.cc b/crypto/asn1/asn1_test.cc index accf3ba..55c0f17 100644 --- a/crypto/asn1/asn1_test.cc +++ b/crypto/asn1/asn1_test.cc
@@ -60,3 +60,30 @@ EXPECT_EQ(Bytes(&kZero, 1), Bytes(obj->value.asn1_string->data, obj->value.asn1_string->length)); } + +TEST(ASN1Test, IntegerSetting) { + bssl::UniquePtr<ASN1_INTEGER> by_bn(M_ASN1_INTEGER_new()); + bssl::UniquePtr<ASN1_INTEGER> by_long(M_ASN1_INTEGER_new()); + bssl::UniquePtr<ASN1_INTEGER> by_uint64(M_ASN1_INTEGER_new()); + bssl::UniquePtr<BIGNUM> bn(BN_new()); + + const std::vector<unsigned> kValues = { + 0, 1, 2, 0xff, 0x100, 0xffff, 0x10000, + }; + for (const auto &i : kValues) { + SCOPED_TRACE(i); + + ASSERT_EQ(1, ASN1_INTEGER_set(by_long.get(), i)); + ASSERT_EQ(1, ASN1_INTEGER_set_uint64(by_uint64.get(), i)); + ASSERT_TRUE(BN_set_word(bn.get(), i)); + ASSERT_TRUE(BN_to_ASN1_INTEGER(bn.get(), by_bn.get())); + + if (i != 0) { + // |ASN1_INTEGER_set| and |BN_to_ASN1_INTEGER| disagree about how to + // encode zero. The former leaves an empty value while the latter encodes + // as a single zero byte. + EXPECT_EQ(0, ASN1_INTEGER_cmp(by_bn.get(), by_long.get())); + } + EXPECT_EQ(0, ASN1_INTEGER_cmp(by_bn.get(), by_uint64.get())); + } +}
diff --git a/crypto/fipsmodule/modes/internal.h b/crypto/fipsmodule/modes/internal.h index f6ee8f4..68ef4dc 100644 --- a/crypto/fipsmodule/modes/internal.h +++ b/crypto/fipsmodule/modes/internal.h
@@ -66,38 +66,6 @@ #define STRICT_ALIGNMENT 0 #endif -#if defined(__GNUC__) && __GNUC__ >= 2 -static inline uint32_t CRYPTO_bswap4(uint32_t x) { - return __builtin_bswap32(x); -} - -static inline uint64_t CRYPTO_bswap8(uint64_t x) { - return __builtin_bswap64(x); -} -#elif defined(_MSC_VER) -OPENSSL_MSVC_PRAGMA(warning(push, 3)) -#include <intrin.h> -OPENSSL_MSVC_PRAGMA(warning(pop)) -#pragma intrinsic(_byteswap_uint64, _byteswap_ulong) -static inline uint32_t CRYPTO_bswap4(uint32_t x) { - return _byteswap_ulong(x); -} - -static inline uint64_t CRYPTO_bswap8(uint64_t x) { - return _byteswap_uint64(x); -} -#else -static inline uint32_t CRYPTO_bswap4(uint32_t x) { - x = (x >> 16) | (x << 16); - x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8); - return x; -} - -static inline uint64_t CRYPTO_bswap8(uint64_t x) { - return CRYPTO_bswap4(x >> 32) | (((uint64_t)CRYPTO_bswap4(x)) << 32); -} -#endif - static inline uint32_t GETU32(const void *in) { uint32_t v; OPENSSL_memcpy(&v, in, sizeof(v));
diff --git a/crypto/internal.h b/crypto/internal.h index 5706414..e6bab02 100644 --- a/crypto/internal.h +++ b/crypto/internal.h
@@ -591,6 +591,41 @@ void *obj, CRYPTO_EX_DATA *ad); +// Endianness conversions. + +#if defined(__GNUC__) && __GNUC__ >= 2 +static inline uint32_t CRYPTO_bswap4(uint32_t x) { + return __builtin_bswap32(x); +} + +static inline uint64_t CRYPTO_bswap8(uint64_t x) { + return __builtin_bswap64(x); +} +#elif defined(_MSC_VER) +OPENSSL_MSVC_PRAGMA(warning(push, 3)) +#include <intrin.h> +OPENSSL_MSVC_PRAGMA(warning(pop)) +#pragma intrinsic(_byteswap_uint64, _byteswap_ulong) +static inline uint32_t CRYPTO_bswap4(uint32_t x) { + return _byteswap_ulong(x); +} + +static inline uint64_t CRYPTO_bswap8(uint64_t x) { + return _byteswap_uint64(x); +} +#else +static inline uint32_t CRYPTO_bswap4(uint32_t x) { + x = (x >> 16) | (x << 16); + x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8); + return x; +} + +static inline uint64_t CRYPTO_bswap8(uint64_t x) { + return CRYPTO_bswap4(x >> 32) | (((uint64_t)CRYPTO_bswap4(x)) << 32); +} +#endif + + // Language bug workarounds. // // Most C standard library functions are undefined if passed NULL, even when the
diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h index 6572995..c7ead03 100644 --- a/include/openssl/asn1.h +++ b/include/openssl/asn1.h
@@ -737,6 +737,7 @@ OPENSSL_EXPORT ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data,int len, const char *sn, const char *ln); OPENSSL_EXPORT int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); +OPENSSL_EXPORT int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v); OPENSSL_EXPORT long ASN1_INTEGER_get(const ASN1_INTEGER *a); OPENSSL_EXPORT ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai); OPENSSL_EXPORT BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai,BIGNUM *bn);