Support the allocating case of i2d_ASN1_{BOOLEAN,OBJECT}.
Imported from upstream's 0971432f6f6d8b40d797133621809bd31eb7bf4e and 7d4c97add12cfa5d4589880b09d6139c3203e2f4, but with missing tests added. Along the way, make Bytes work with any Span<const uint8_t>-convertable type. Change-Id: If365f981fe8a8274e12000309ffd99b1bb719842 Reviewed-on: https://boringssl-review.googlesource.com/31086 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
parent
378cca8016
commit
c4131a4a23
@ -62,17 +62,30 @@
|
|||||||
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
|
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
unsigned char *p;
|
unsigned char *p, *allocated = NULL;
|
||||||
|
|
||||||
r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN);
|
r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN);
|
||||||
if (pp == NULL)
|
if (pp == NULL)
|
||||||
return (r);
|
return (r);
|
||||||
p = *pp;
|
|
||||||
|
if (*pp == NULL) {
|
||||||
|
if ((p = allocated = OPENSSL_malloc(r)) == NULL) {
|
||||||
|
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p = *pp;
|
||||||
|
}
|
||||||
|
|
||||||
ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
|
ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
|
||||||
*(p++) = (unsigned char)a;
|
*p = (unsigned char)a;
|
||||||
*pp = p;
|
|
||||||
return (r);
|
/*
|
||||||
|
* If a new buffer was allocated, just return it back.
|
||||||
|
* If not, return the incremented buffer pointer.
|
||||||
|
*/
|
||||||
|
*pp = allocated != NULL ? allocated : p + 1;
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
|
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
|
|
||||||
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
|
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
unsigned char *p, *allocated = NULL;
|
||||||
int objsize;
|
int objsize;
|
||||||
|
|
||||||
if ((a == NULL) || (a->data == NULL))
|
if ((a == NULL) || (a->data == NULL))
|
||||||
@ -78,13 +78,24 @@ int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
|
|||||||
if (pp == NULL || objsize == -1)
|
if (pp == NULL || objsize == -1)
|
||||||
return objsize;
|
return objsize;
|
||||||
|
|
||||||
p = *pp;
|
if (*pp == NULL) {
|
||||||
|
if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) {
|
||||||
|
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p = *pp;
|
||||||
|
}
|
||||||
|
|
||||||
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
|
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
|
||||||
OPENSSL_memcpy(p, a->data, a->length);
|
OPENSSL_memcpy(p, a->data, a->length);
|
||||||
p += a->length;
|
|
||||||
|
|
||||||
*pp = p;
|
/*
|
||||||
return (objsize);
|
* If a new buffer was allocated, just return it back.
|
||||||
|
* If not, return the incremented buffer pointer.
|
||||||
|
*/
|
||||||
|
*pp = allocated != NULL ? allocated : p + a->length;
|
||||||
|
return objsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
|
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include <openssl/bytestring.h>
|
#include <openssl/bytestring.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/mem.h>
|
#include <openssl/mem.h>
|
||||||
|
#include <openssl/obj.h>
|
||||||
|
#include <openssl/span.h>
|
||||||
|
|
||||||
#include "../test/test_util.h"
|
#include "../test/test_util.h"
|
||||||
|
|
||||||
@ -148,3 +150,37 @@ TEST(ASN1Test, Recursive) {
|
|||||||
// is too deep, so the |ASN1_R_NESTED_TOO_DEEP| entry drops off the queue.
|
// is too deep, so the |ASN1_R_NESTED_TOO_DEEP| entry drops off the queue.
|
||||||
ASN1_LINKED_LIST_free(list);
|
ASN1_LINKED_LIST_free(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void TestSerialize(T obj, int (*i2d_func)(T a, uint8_t **pp),
|
||||||
|
bssl::Span<const uint8_t> expected) {
|
||||||
|
int len = static_cast<int>(expected.size());
|
||||||
|
ASSERT_EQ(i2d_func(obj, nullptr), len);
|
||||||
|
|
||||||
|
std::vector<uint8_t> buf(expected.size());
|
||||||
|
uint8_t *ptr = buf.data();
|
||||||
|
ASSERT_EQ(i2d_func(obj, &ptr), len);
|
||||||
|
EXPECT_EQ(ptr, buf.data() + buf.size());
|
||||||
|
EXPECT_EQ(Bytes(expected), Bytes(buf));
|
||||||
|
|
||||||
|
// Test the allocating version.
|
||||||
|
ptr = nullptr;
|
||||||
|
ASSERT_EQ(i2d_func(obj, &ptr), len);
|
||||||
|
EXPECT_EQ(Bytes(expected), Bytes(ptr, expected.size()));
|
||||||
|
OPENSSL_free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ASN1Test, SerializeObject) {
|
||||||
|
static const uint8_t kDER[] = {0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
|
||||||
|
0xf7, 0x0d, 0x01, 0x01, 0x01};
|
||||||
|
const ASN1_OBJECT *obj = OBJ_nid2obj(NID_rsaEncryption);
|
||||||
|
TestSerialize(const_cast<ASN1_OBJECT *>(obj), i2d_ASN1_OBJECT, kDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ASN1Test, SerializeBoolean) {
|
||||||
|
static const uint8_t kTrue[] = {0x01, 0x01, 0xff};
|
||||||
|
TestSerialize(0xff, i2d_ASN1_BOOLEAN, kTrue);
|
||||||
|
|
||||||
|
static const uint8_t kFalse[] = {0x01, 0x01, 0x00};
|
||||||
|
TestSerialize(0x00, i2d_ASN1_BOOLEAN, kFalse);
|
||||||
|
}
|
||||||
|
@ -30,15 +30,15 @@ void hexdump(FILE *fp, const char *msg, const void *in, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const Bytes &in) {
|
std::ostream &operator<<(std::ostream &os, const Bytes &in) {
|
||||||
if (in.len == 0) {
|
if (in.span_.empty()) {
|
||||||
return os << "<empty Bytes>";
|
return os << "<empty Bytes>";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print a byte slice as hex.
|
// Print a byte slice as hex.
|
||||||
static const char hex[] = "0123456789abcdef";
|
static const char hex[] = "0123456789abcdef";
|
||||||
for (size_t i = 0; i < in.len; i++) {
|
for (uint8_t b : in.span_) {
|
||||||
os << hex[in.data[i] >> 4];
|
os << hex[b >> 4];
|
||||||
os << hex[in.data[i] & 0xf];
|
os << hex[b & 0xf];
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <openssl/span.h>
|
||||||
|
|
||||||
#include "../internal.h"
|
#include "../internal.h"
|
||||||
|
|
||||||
|
|
||||||
@ -35,26 +37,22 @@ void hexdump(FILE *fp, const char *msg, const void *in, size_t len);
|
|||||||
// allows it to be used in EXPECT_EQ macros.
|
// allows it to be used in EXPECT_EQ macros.
|
||||||
struct Bytes {
|
struct Bytes {
|
||||||
Bytes(const uint8_t *data_arg, size_t len_arg)
|
Bytes(const uint8_t *data_arg, size_t len_arg)
|
||||||
: data(data_arg), len(len_arg) {}
|
: span_(data_arg, len_arg) {}
|
||||||
Bytes(const char *data_arg, size_t len_arg)
|
Bytes(const char *data_arg, size_t len_arg)
|
||||||
: data(reinterpret_cast<const uint8_t *>(data_arg)), len(len_arg) {}
|
: span_(reinterpret_cast<const uint8_t *>(data_arg), len_arg) {}
|
||||||
|
|
||||||
explicit Bytes(const char *str)
|
explicit Bytes(const char *str)
|
||||||
: data(reinterpret_cast<const uint8_t *>(str)), len(strlen(str)) {}
|
: span_(reinterpret_cast<const uint8_t *>(str), strlen(str)) {}
|
||||||
explicit Bytes(const std::string &str)
|
explicit Bytes(const std::string &str)
|
||||||
: data(reinterpret_cast<const uint8_t *>(str.data())), len(str.size()) {}
|
: span_(reinterpret_cast<const uint8_t *>(str.data()), str.size()) {}
|
||||||
explicit Bytes(const std::vector<uint8_t> &vec)
|
explicit Bytes(bssl::Span<const uint8_t> span)
|
||||||
: data(vec.data()), len(vec.size()) {}
|
: span_(span) {}
|
||||||
|
|
||||||
template <size_t N>
|
bssl::Span<const uint8_t> span_;
|
||||||
explicit Bytes(const uint8_t (&array)[N]) : data(array), len(N) {}
|
|
||||||
|
|
||||||
const uint8_t *data;
|
|
||||||
size_t len;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(const Bytes &a, const Bytes &b) {
|
inline bool operator==(const Bytes &a, const Bytes &b) {
|
||||||
return a.len == b.len && OPENSSL_memcmp(a.data, b.data, a.len) == 0;
|
return a.span_ == b.span_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator!=(const Bytes &a, const Bytes &b) { return !(a == b); }
|
inline bool operator!=(const Bytes &a, const Bytes &b) { return !(a == b); }
|
||||||
|
Loading…
Reference in New Issue
Block a user