Skip to content

Commit 17c3b3c

Browse files
fix(webauthn): Extra checks for algorithm, and public key parts
1 parent f38ba3b commit 17c3b3c

File tree

3 files changed

+39
-15
lines changed

3 files changed

+39
-15
lines changed

src/Cbor.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,11 @@ uint32_t Decode::getTotalLen() const {
246246
}
247247
}
248248

249+
Decode::MajorType Decode::getMajorType() const {
250+
TypeDesc typeDesc = getTypeDesc();
251+
return typeDesc.majorType;
252+
}
253+
249254
uint64_t Decode::getValue() const {
250255
TypeDesc typeDesc = getTypeDesc();
251256
if (typeDesc.majorType != MT_uint && typeDesc.majorType != MT_negint) {

src/Cbor.h

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,22 @@ class Decode {
8585
/// Constructor, create from CBOR byte stream
8686
Decode(const Data& input);
8787

88-
public: // decoding
88+
public:
89+
enum MajorType {
90+
MT_uint = 0,
91+
MT_negint = 1,
92+
MT_bytes = 2,
93+
MT_string = 3,
94+
MT_array = 4,
95+
MT_map = 5,
96+
MT_tag = 6,
97+
MT_special = 7,
98+
};
99+
89100
/// Check if contains a valid CBOR byte stream.
90101
bool isValid() const;
102+
// Get the major type
103+
MajorType getMajorType() const;
91104
/// Get the value of a simple type
92105
uint64_t getValue() const;
93106
/// Get the value of a string/bytes as string
@@ -107,17 +120,6 @@ class Decode {
107120
uint32_t length() const { return subLen; }
108121
/// Return encoded form (useful e.g for parsed out sub-parts)
109122
Data encoded() const;
110-
111-
enum MajorType {
112-
MT_uint = 0,
113-
MT_negint = 1,
114-
MT_bytes = 2,
115-
MT_string = 3,
116-
MT_array = 4,
117-
MT_map = 5,
118-
MT_tag = 6,
119-
MT_special = 7,
120-
};
121123

122124
private:
123125
/// Struct used to keep reference to original data

src/WebAuthn.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ namespace TW::WebAuthn {
1616
static const std::size_t gAuthDataMinSize = 37;
1717
// 16 aaguid + 2 credIDLen
1818
static const std::size_t gAuthCredentialDataMinSize = 18;
19+
// 6 = -gAlgES256 - 1, where gAlgES256 = -7, ES256 = ECDSA w/ SHA-256 on P-256 curve
20+
static const uint64_t gAlgES256Encoded = 6;
1921

2022
// https://www.w3.org/TR/webauthn-2/#authenticator-data
2123
struct AuthData {
@@ -125,17 +127,32 @@ std::optional<PublicKey> getPublicKey(const Data& attestationObject) {
125127
// https://www.w3.org/TR/webauthn-2/#sctn-encoded-credPubKey-examples
126128
const std::string xKey = "-2";
127129
const std::string yKey = "-3";
130+
const std::string algKey = "3";
128131

129132
const auto x = findIntKey(COSEPublicKey, xKey);
130133
const auto y = findIntKey(COSEPublicKey, yKey);
131-
if (x == COSEPublicKey.end() || y == COSEPublicKey.end()) {
134+
const auto alg = findIntKey(COSEPublicKey, algKey);
135+
if (x == COSEPublicKey.end() || y == COSEPublicKey.end() || alg == COSEPublicKey.end()) {
132136
return std::nullopt;
133137
}
134138

139+
if (alg->second.getMajorType() != Cbor::Decode::MajorType::MT_negint) {
140+
return std::nullopt;
141+
}
142+
// Currently, we only support P256 public keys.
143+
if (alg->second.getValue() != gAlgES256Encoded) {
144+
return std::nullopt;
145+
}
146+
147+
const auto xBytes = x->second.getBytes();
148+
const auto yBytes = y->second.getBytes();
149+
if (xBytes.size() != 32 || yBytes.size() != 32) {
150+
return std::nullopt;
151+
}
135152
Data publicKey;
136153
append(publicKey, 0x04);
137-
append(publicKey, x->second.getBytes());
138-
append(publicKey, y->second.getBytes());
154+
append(publicKey, xBytes);
155+
append(publicKey, yBytes);
139156

140157
return PublicKey(publicKey, TWPublicKeyTypeNIST256p1Extended);
141158
} catch (...) {

0 commit comments

Comments
 (0)