CDC Badge OS
Firmware for the CDC Badge v1.0 hardware security key
Loading...
Searching...
No Matches
algo_attr.cpp
Go to the documentation of this file.
1
8
10
11#include <string.h>
12
13namespace {
14
15// OIDs are stored without leading tag/length bytes, exactly as carried in
16// the algorithm-attribute DO payload.
17
18constexpr uint8_t kOidP256[] = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 };
19constexpr uint8_t kOidEd25519[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01 };
20constexpr uint8_t kOidX25519[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01 };
21
22constexpr size_t kP256Len = sizeof(kOidP256);
23constexpr size_t kEd25519Len = sizeof(kOidEd25519);
24constexpr size_t kX25519Len = sizeof(kOidX25519);
25
26algo_attr_curve_t classify_oid(const uint8_t *oid, size_t len) {
27 if (len == kP256Len && memcmp(oid, kOidP256, len) == 0) return ALGO_ATTR_CURVE_P256;
28 if (len == kEd25519Len && memcmp(oid, kOidEd25519, len) == 0) return ALGO_ATTR_CURVE_ED25519;
29 if (len == kX25519Len && memcmp(oid, kOidX25519, len) == 0) return ALGO_ATTR_CURVE_X25519;
31}
32
33bool curve_to_oid(algo_attr_curve_t curve, const uint8_t **out, size_t *out_len) {
34 switch (curve) {
35 case ALGO_ATTR_CURVE_P256: *out = kOidP256; *out_len = kP256Len; return true;
36 case ALGO_ATTR_CURVE_ED25519: *out = kOidEd25519; *out_len = kEd25519Len; return true;
37 case ALGO_ATTR_CURVE_X25519: *out = kOidX25519; *out_len = kX25519Len; return true;
38 default: return false;
39 }
40}
41
42bool is_known_algo(uint8_t id) {
43 return id == ALGO_ATTR_ID_RSA || id == ALGO_ATTR_ID_ECDH ||
45}
46
47bool is_rsa_modulus_bits(uint16_t n_bits) {
48 return n_bits == 2048 || n_bits == 3072 || n_bits == 4096;
49}
50
51} // namespace
52
53algo_attr_status_t algo_attr_parse(const uint8_t *bytes, size_t len, algo_attr_t *out) {
54 if (!bytes || !out) return ALGO_ATTR_ERR_NULL;
55 if (len < 2) return ALGO_ATTR_ERR_TOO_SHORT;
56
57 memset(out, 0, sizeof(*out));
58 out->algo_id = bytes[0];
59 if (!is_known_algo(out->algo_id)) return ALGO_ATTR_ERR_BAD_ALGO;
60 out->is_rsa = (out->algo_id == ALGO_ATTR_ID_RSA);
61
62 if (out->is_rsa) {
63 if (len < 6) return ALGO_ATTR_ERR_BAD_RSA;
64 out->rsa_n_bits = static_cast<uint16_t>((bytes[1] << 8) | bytes[2]);
65 out->rsa_e_bits = static_cast<uint16_t>((bytes[3] << 8) | bytes[4]);
66 out->rsa_import_fmt = bytes[5];
67 if (!is_rsa_modulus_bits(out->rsa_n_bits)) return ALGO_ATTR_ERR_BAD_RSA;
68 if (out->rsa_e_bits == 0 || out->rsa_e_bits > 64) return ALGO_ATTR_ERR_BAD_RSA;
69 if (out->rsa_import_fmt > 0x03) return ALGO_ATTR_ERR_BAD_RSA;
70 return ALGO_ATTR_OK;
71 }
72
73 // ECC path: bytes[1..] is the OID; an optional trailing 0xFF flags the
74 // standard public-key import format.
75 const uint8_t *oid = bytes + 1;
76 size_t oid_len = len - 1;
77 if (oid_len > 0 && oid[oid_len - 1] == 0xFF) {
78 out->has_import_format = true;
79 out->import_format = 0xFF;
80 oid_len -= 1;
81 }
82 out->curve = classify_oid(oid, oid_len);
83 return ALGO_ATTR_OK;
84}
85
87 size_t out_cap, size_t *out_len) {
88 if (!attr || !out || !out_len) return ALGO_ATTR_ERR_NULL;
89 if (!is_known_algo(attr->algo_id)) return ALGO_ATTR_ERR_BAD_ALGO;
90
91 if (attr->algo_id == ALGO_ATTR_ID_RSA) {
92 if (!is_rsa_modulus_bits(attr->rsa_n_bits)) return ALGO_ATTR_ERR_BAD_RSA;
93 if (out_cap < 6) return ALGO_ATTR_ERR_BUF_TOO_SMALL;
94 out[0] = attr->algo_id;
95 out[1] = static_cast<uint8_t>((attr->rsa_n_bits >> 8) & 0xFF);
96 out[2] = static_cast<uint8_t>(attr->rsa_n_bits & 0xFF);
97 out[3] = static_cast<uint8_t>((attr->rsa_e_bits >> 8) & 0xFF);
98 out[4] = static_cast<uint8_t>(attr->rsa_e_bits & 0xFF);
99 out[5] = attr->rsa_import_fmt;
100 *out_len = 6;
101 return ALGO_ATTR_OK;
102 }
103
104 const uint8_t *oid = nullptr;
105 size_t oid_len = 0;
106 if (!curve_to_oid(attr->curve, &oid, &oid_len)) return ALGO_ATTR_ERR_BAD_CURVE;
107
108 const size_t need = 1 + oid_len + (attr->has_import_format ? 1 : 0);
109 if (out_cap < need) return ALGO_ATTR_ERR_BUF_TOO_SMALL;
110 out[0] = attr->algo_id;
111 memcpy(out + 1, oid, oid_len);
112 if (attr->has_import_format) {
113 out[1 + oid_len] = attr->import_format;
114 }
115 *out_len = need;
116 return ALGO_ATTR_OK;
117}
118
120 algo_attr_role_t role) {
121 if (!attr) return ALGO_ATTR_ERR_NULL;
122 if (attr->is_rsa) return ALGO_ATTR_OK; // RSA works for any role.
123
124 switch (role) {
127 if (attr->algo_id == ALGO_ATTR_ID_ECDSA || attr->algo_id == ALGO_ATTR_ID_EDDSA) {
128 return ALGO_ATTR_OK;
129 }
132 if (attr->algo_id == ALGO_ATTR_ID_ECDH) return ALGO_ATTR_OK;
134 }
136}
137
139 bool rsa_supported) {
140 if (!attr) return ALGO_ATTR_ERR_NULL;
141 if (attr->is_rsa) {
142 return rsa_supported ? ALGO_ATTR_OK : ALGO_ATTR_ERR_BAD_RSA;
143 }
144 switch (attr->curve) {
146 if (attr->algo_id == ALGO_ATTR_ID_ECDSA || attr->algo_id == ALGO_ATTR_ID_ECDH) {
147 return ALGO_ATTR_OK;
148 }
154 default:
156 }
157}
algo_attr_status_t algo_attr_validate_role(const algo_attr_t *attr, algo_attr_role_t role)
Check whether the parsed attribute is compatible with the key role it will be installed into.
algo_attr_status_t algo_attr_parse(const uint8_t *bytes, size_t len, algo_attr_t *out)
Parse a raw algorithm-attribute byte sequence into structured form.
Definition algo_attr.cpp:53
algo_attr_status_t algo_attr_validate_capability(const algo_attr_t *attr, bool rsa_supported)
Check whether the badge's secure element / mbedTLS combination can actually execute this algorithm.
algo_attr_status_t algo_attr_build(const algo_attr_t *attr, uint8_t *out, size_t out_cap, size_t *out_len)
Serialise an algorithm-attribute structure to bytes.
Definition algo_attr.cpp:86
algo_attr_role_t
Key role (selects which DO tag is being parsed / built).
Definition algo_attr.h:56
@ ALGO_ATTR_ROLE_AUT
Definition algo_attr.h:59
@ ALGO_ATTR_ROLE_DEC
Definition algo_attr.h:58
@ ALGO_ATTR_ROLE_SIG
Definition algo_attr.h:57
algo_attr_curve_t
Curves the firmware recognises. UNKNOWN flags unsupported OIDs.
Definition algo_attr.h:48
@ ALGO_ATTR_CURVE_X25519
Definition algo_attr.h:52
@ ALGO_ATTR_CURVE_P256
Definition algo_attr.h:50
@ ALGO_ATTR_CURVE_UNKNOWN
Definition algo_attr.h:49
@ ALGO_ATTR_CURVE_ED25519
Definition algo_attr.h:51
algo_attr_status_t
Outcome of algo-attribute operations.
Definition algo_attr.h:77
@ ALGO_ATTR_ERR_BAD_CURVE
Definition algo_attr.h:81
@ ALGO_ATTR_ERR_BAD_ALGO
Definition algo_attr.h:80
@ ALGO_ATTR_ERR_BUF_TOO_SMALL
Definition algo_attr.h:84
@ ALGO_ATTR_OK
Definition algo_attr.h:78
@ ALGO_ATTR_ERR_NULL
Definition algo_attr.h:85
@ ALGO_ATTR_ERR_TOO_SHORT
Definition algo_attr.h:79
@ ALGO_ATTR_ERR_BAD_RSA
Definition algo_attr.h:82
@ ALGO_ATTR_ERR_ROLE_MISMATCH
Definition algo_attr.h:83
@ ALGO_ATTR_ID_ECDH
Definition algo_attr.h:42
@ ALGO_ATTR_ID_ECDSA
Definition algo_attr.h:43
@ ALGO_ATTR_ID_RSA
Definition algo_attr.h:41
@ ALGO_ATTR_ID_EDDSA
Definition algo_attr.h:44
uint8_t curve
Parsed algorithm-attribute payload.
Definition algo_attr.h:63
uint16_t rsa_n_bits
Definition algo_attr.h:71
bool has_import_format
Definition algo_attr.h:68
algo_attr_curve_t curve
Definition algo_attr.h:67
uint16_t rsa_e_bits
Definition algo_attr.h:72
uint8_t import_format
Definition algo_attr.h:69
uint8_t rsa_import_fmt
Definition algo_attr.h:73
bool is_rsa
Definition algo_attr.h:65
uint8_t algo_id
Definition algo_attr.h:64