Botan 3.13.0
Crypto and TLS for C&
Botan::X509_Serial_Number Class Referencefinal

#include <pkix_types.h>

Inheritance diagram for Botan::X509_Serial_Number:
Botan::ASN1_Object

Public Member Functions

std::vector< uint8_t > BER_encode () const
bool conforms_to_rfc5280 () const
void decode_from (BER_Decoder &from) override
std::span< const uint8_t > der_contents () const
void encode_into (DER_Encoder &to) const override
bool is_negative () const
bool is_zero () const
std::vector< uint8_t > magnitude () const
size_t octet_length () const
std::strong_ordering operator<=> (const X509_Serial_Number &other) const
bool operator== (const X509_Serial_Number &other) const
BigInt to_bigint () const
std::string to_string () const
 X509_Serial_Number ()
 X509_Serial_Number (const BigInt &value)

Static Public Member Functions

static X509_Serial_Number from_bytes (std::span< const uint8_t > bytes)
static X509_Serial_Number from_der_contents (std::span< const uint8_t > contents)
static X509_Serial_Number random (RandomNumberGenerator &rng)

Detailed Description

X.509 certificate serial number (RFC 5280 CertificateSerialNumber)

Stores the value as the contents octets of the DER INTEGER encoding (two's complement, minimal length), so the sign is preserved and equality on the stored bytes is value equality.

RFC 5280 4.1.2.2: The serial number MUST be a positive integer assigned by the CA to each certificate. and Note: Non-conforming CAs may issue certificates with serial numbers that are negative or zero. Certificate users SHOULD be prepared to gracefully handle such certificates.

so non-conforming values are representable, and can be detected with is_negative, is_zero and octet_length.

Definition at line 65 of file pkix_types.h.

Constructor & Destructor Documentation

◆ X509_Serial_Number() [1/2]

Botan::X509_Serial_Number::X509_Serial_Number ( )
inline

Serial number zero

Definition at line 70 of file pkix_types.h.

70: m_contents{0x00} {}

Referenced by decode_from(), from_bytes(), from_der_contents(), operator<=>(), operator==(), and random().

◆ X509_Serial_Number() [2/2]

Botan::X509_Serial_Number::X509_Serial_Number ( const BigInt & value)
explicit

Create from an integer value

Definition at line 20 of file x509_serial.cpp.

20: m_contents(ASN1::integer_contents(value)) {}
std::vector< uint8_t > integer_contents(const BigInt &n)
Definition der_enc.cpp:356

Member Function Documentation

◆ BER_encode()

std::vector< uint8_t > Botan::ASN1_Object::BER_encode ( ) const
inherited

Return the encoding of this object. This is a convenience method when just one object needs to be serialized. Use DER_Encoder for complicated encodings.

Definition at line 21 of file asn1_obj.cpp.

21 {
22 std::vector<uint8_t> output;
23 DER_Encoder der(output);
24 this->encode_into(der);
25 return output;
26}
virtual void encode_into(DER_Encoder &to) const =0

References encode_into().

Referenced by decode_from(), Botan::PKCS12::export_to(), Botan::Certificate_Store_In_SQL::find_all_certs(), Botan::Certificate_Store_In_SQL::find_cert(), Botan::X509_Certificate::fingerprint(), Botan::Certificate_Store_In_SQL::insert_cert(), Botan::X509_Object::PEM_encode(), and Botan::PSS_Params::PSS_Params().

◆ conforms_to_rfc5280()

bool Botan::X509_Serial_Number::conforms_to_rfc5280 ( ) const
inline

True if this serial number satisfies the RFC 5280 4.1.2.2 rules for conforming CAs: a positive integer of at most 20 octets

Definition at line 118 of file pkix_types.h.

118{ return !is_negative() && !is_zero() && octet_length() <= 20; }
size_t octet_length() const
Definition pkix_types.h:112

References is_negative(), is_zero(), and octet_length().

◆ decode_from()

void Botan::X509_Serial_Number::decode_from ( BER_Decoder & from)
overridevirtual

Decode whatever this object is from from

Parameters
fromthe BER_Decoder that will be read from

Implements Botan::ASN1_Object.

Definition at line 108 of file x509_serial.cpp.

108 {
109 // Decode via BigInt so the decoder's limits apply, in particular the
110 // rejection of non-minimal INTEGER encodings in DER mode
111 BigInt value;
112 from.decode(value);
113 *this = X509_Serial_Number(value);
114}

References Botan::BER_Decoder::decode(), and X509_Serial_Number().

◆ der_contents()

std::span< const uint8_t > Botan::X509_Serial_Number::der_contents ( ) const
inline

The contents octets of the DER INTEGER encoding (big-endian two's complement, minimal length)

Definition at line 124 of file pkix_types.h.

124{ return m_contents; }

◆ encode_into()

void Botan::X509_Serial_Number::encode_into ( DER_Encoder & to) const
overridevirtual

Encode whatever this object is into to

Parameters
tothe DER_Encoder that will be written to

Implements Botan::ASN1_Object.

Definition at line 103 of file x509_serial.cpp.

103 {
104 BOTAN_STATE_CHECK(!m_contents.empty());
105 to.add_object(ASN1_Type::Integer, ASN1_Class::Universal, m_contents);
106}
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49

References Botan::DER_Encoder::add_object(), BOTAN_STATE_CHECK, Botan::Integer, and Botan::Universal.

◆ from_bytes()

X509_Serial_Number Botan::X509_Serial_Number::from_bytes ( std::span< const uint8_t > bytes)
static

Create from an unsigned big-endian encoded integer

Definition at line 22 of file x509_serial.cpp.

22 {
23 while(!bytes.empty() && bytes.front() == 0x00) {
24 bytes = bytes.subspan(1);
25 }
26
27 if(bytes.empty()) {
28 return X509_Serial_Number(); // zero
29 }
30
32 sn.m_contents.clear();
33 if((bytes.front() & 0x80) == 0x80) {
34 sn.m_contents.push_back(0x00);
35 }
36 sn.m_contents.insert(sn.m_contents.end(), bytes.begin(), bytes.end());
37 return sn;
38}

References X509_Serial_Number().

Referenced by random().

◆ from_der_contents()

X509_Serial_Number Botan::X509_Serial_Number::from_der_contents ( std::span< const uint8_t > contents)
static

Create from the contents octets of a BER INTEGER (big-endian two's complement). Redundant leading octets are normalized away; an empty input is rejected.

Definition at line 40 of file x509_serial.cpp.

40 {
41 if(contents.empty()) {
42 throw Decoding_Error("Serial number INTEGER encoding has no contents octets");
43 }
44
45 // Normalize away redundant leading octets a BER encoding may carry
46 size_t offset = 0;
47 while(offset + 1 < contents.size() && ((contents[offset] == 0x00 && (contents[offset + 1] & 0x80) == 0x00) ||
48 (contents[offset] == 0xFF && (contents[offset + 1] & 0x80) == 0x80))) {
49 offset += 1;
50 }
51
53 sn.m_contents.assign(contents.begin() + offset, contents.end());
54 return sn;
55}

References X509_Serial_Number().

◆ is_negative()

bool Botan::X509_Serial_Number::is_negative ( ) const

Return true if the serial number is negative

TODO(Botan4) remove this once negative serial numbers are prohibited

Definition at line 65 of file x509_serial.cpp.

65 {
66 BOTAN_STATE_CHECK(!m_contents.empty());
67 return (m_contents[0] & 0x80) == 0x80;
68}

References BOTAN_STATE_CHECK.

Referenced by Botan::PKIX::check_chain(), conforms_to_rfc5280(), Botan::X509_Certificate::is_serial_negative(), magnitude(), operator<=>(), and to_string().

◆ is_zero()

bool Botan::X509_Serial_Number::is_zero ( ) const

Return true if the serial number is the integer zero

Definition at line 70 of file x509_serial.cpp.

70 {
71 return m_contents.size() == 1 && m_contents[0] == 0x00;
72}

Referenced by conforms_to_rfc5280(), magnitude(), and to_string().

◆ magnitude()

std::vector< uint8_t > Botan::X509_Serial_Number::magnitude ( ) const

The absolute value as unsigned big-endian bytes without leading zeros. Note this loses the sign, and is empty for a zero serial; it matches X509_Certificate::serial_number.

Definition at line 74 of file x509_serial.cpp.

74 {
75 BOTAN_STATE_CHECK(!m_contents.empty());
76
77 if(is_zero()) {
78 return {};
79 } else if(is_negative()) {
80 return to_bigint().serialize();
81 } else if(m_contents[0] == 0x00) {
82 // Positive value whose leading magnitude bit is set; skip the sign octet
83 return {m_contents.begin() + 1, m_contents.end()};
84 } else {
85 return m_contents;
86 }
87}
T serialize(size_t len) const
Definition bigint.h:790

References BOTAN_STATE_CHECK, is_negative(), is_zero(), Botan::BigInt::serialize(), and to_bigint().

Referenced by to_string().

◆ octet_length()

size_t Botan::X509_Serial_Number::octet_length ( ) const
inline

Number of contents octets in the DER encoding of this value

Definition at line 112 of file pkix_types.h.

112{ return m_contents.size(); }

Referenced by conforms_to_rfc5280().

◆ operator<=>()

std::strong_ordering Botan::X509_Serial_Number::operator<=> ( const X509_Serial_Number & other) const

Numeric ordering

Definition at line 116 of file x509_serial.cpp.

116 =>(const X509_Serial_Number& other) const {
117 BOTAN_STATE_CHECK(!m_contents.empty());
118
119 const bool neg = is_negative();
120
121 if(neg != other.is_negative()) {
122 return neg ? std::strong_ordering::less : std::strong_ordering::greater;
123 }
124
125 // Same sign: for positive values the longer encoding is the larger value,
126 // for negative values the longer encoding is the smaller (more negative)
127 if(m_contents.size() != other.m_contents.size()) {
128 const bool shorter = m_contents.size() < other.m_contents.size();
129 return (shorter != neg) ? std::strong_ordering::less : std::strong_ordering::greater;
130 }
131
132 /*
133 * When comparing two values of the same sign in two's complement
134 * encoding, the lexicographic ordering is correct for both signs,
135 * for instance -2 (0xFE) is less than -1 (0xFF)
136 */
137 const int cmp = std::memcmp(m_contents.data(), other.m_contents.data(), m_contents.size());
138 if(cmp < 0) {
139 return std::strong_ordering::less;
140 } else if(cmp > 0) {
141 return std::strong_ordering::greater;
142 } else {
143 return std::strong_ordering::equal;
144 }
145}

References BOTAN_STATE_CHECK, is_negative(), and X509_Serial_Number().

◆ operator==()

bool Botan::X509_Serial_Number::operator== ( const X509_Serial_Number & other) const
inline

Definition at line 143 of file pkix_types.h.

143{ return m_contents == other.m_contents; }

References X509_Serial_Number().

◆ random()

X509_Serial_Number Botan::X509_Serial_Number::random ( RandomNumberGenerator & rng)
static

Generate a serial number suitable for issuing a certificate.

The result is positive, never zero, and contains 126 bits of output from the RNG. The topmost bit is cleared, and the 127th bit is set.

Definition at line 57 of file x509_serial.cpp.

57 {
58 std::array<uint8_t, 16> bytes{};
59 rng.randomize(bytes);
60 bytes[0] &= 0x7F; // clear bit 128
61 bytes[0] |= 0x40; // set bit 127
63}
static X509_Serial_Number from_bytes(std::span< const uint8_t > bytes)

References from_bytes(), Botan::RandomNumberGenerator::randomize(), and X509_Serial_Number().

Referenced by Botan::X509_CA::make_cert().

◆ to_bigint()

BigInt Botan::X509_Serial_Number::to_bigint ( ) const

Definition at line 89 of file x509_serial.cpp.

89 {
90 BOTAN_STATE_CHECK(!m_contents.empty());
91 return ASN1::integer_from_contents(m_contents);
92}
BigInt integer_from_contents(std::span< const uint8_t > contents)
Definition ber_dec.cpp:801

References BOTAN_STATE_CHECK, and Botan::ASN1::integer_from_contents().

Referenced by botan_x509_cert_serial_number(), botan_x509_crl_entry_serial_number(), and magnitude().

◆ to_string()

std::string Botan::X509_Serial_Number::to_string ( ) const

The value in hex, prefixed with '-' if negative

Definition at line 94 of file x509_serial.cpp.

94 {
95 BOTAN_STATE_CHECK(!m_contents.empty());
96 if(is_zero()) {
97 return "00";
98 }
99 const std::string hex = hex_encode(magnitude());
100 return is_negative() ? "-" + hex : hex;
101}
std::vector< uint8_t > magnitude() const
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition hex.cpp:34

References BOTAN_STATE_CHECK, Botan::hex_encode(), is_negative(), is_zero(), and magnitude().

Referenced by Botan::X509_Certificate::to_string().


The documentation for this class was generated from the following files: