Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / dom / webauthn / WebAuthnCBORUtil.cpp
blob51255e80d8ae898a0b186ec2b857c30c3ceca759
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "cbor-cpp/src/cbor.h"
8 #include "mozilla/dom/WebAuthnCBORUtil.h"
9 #include "mozilla/dom/WebAuthnUtil.h"
11 namespace mozilla::dom {
13 nsresult CBOREncodePublicKeyObj(const CryptoBuffer& aPubKeyBuf,
14 /* out */ CryptoBuffer& aPubKeyObj) {
15 mozilla::dom::CryptoBuffer xBuf, yBuf;
16 nsresult rv = U2FDecomposeECKey(aPubKeyBuf, xBuf, yBuf);
17 if (NS_FAILED(rv)) {
18 return rv;
21 // COSE_Key object. See https://tools.ietf.org/html/rfc8152#section-7
22 cbor::output_dynamic cborPubKeyOut;
23 cbor::encoder encoder(cborPubKeyOut);
24 encoder.write_map(5);
26 encoder.write_int(1); // kty
27 encoder.write_int(2); // EC2
28 encoder.write_int(3); // alg
29 encoder.write_int(-7); // ES256
31 // See https://tools.ietf.org/html/rfc8152#section-13.1
32 encoder.write_int(-1); // crv
33 encoder.write_int(1); // P-256
34 encoder.write_int(-2); // x
35 encoder.write_bytes(xBuf.Elements(), xBuf.Length());
36 encoder.write_int(-3); // y
37 encoder.write_bytes(yBuf.Elements(), yBuf.Length());
40 if (!aPubKeyObj.Assign(cborPubKeyOut.data(), cborPubKeyOut.size())) {
41 return NS_ERROR_OUT_OF_MEMORY;
43 return NS_OK;
46 nsresult CBOREncodeFidoU2FAttestationObj(
47 const CryptoBuffer& aAuthDataBuf, const CryptoBuffer& aAttestationCertBuf,
48 const CryptoBuffer& aSignatureBuf,
49 /* out */ CryptoBuffer& aAttestationObj) {
51 Attestation Object, encoded in CBOR (description is CDDL)
53 attObj = {
54 authData: bytes,
55 $$attStmtType
57 $$attStmtType //= (
58 fmt: "fido-u2f",
59 attStmt: u2fStmtFormat
61 u2fStmtFormat = {
62 x5c: [ attestnCert: bytes, * (caCert: bytes) ],
63 sig: bytes
66 cbor::output_dynamic cborAttOut;
67 cbor::encoder encoder(cborAttOut);
68 encoder.write_map(3);
70 encoder.write_string("fmt");
71 encoder.write_string("fido-u2f");
73 encoder.write_string("attStmt");
74 encoder.write_map(2);
76 encoder.write_string("sig");
77 encoder.write_bytes(aSignatureBuf.Elements(), aSignatureBuf.Length());
79 encoder.write_string("x5c");
80 // U2F wire protocol can only deliver 1 certificate, so it's never a chain
81 encoder.write_array(1);
82 encoder.write_bytes(aAttestationCertBuf.Elements(),
83 aAttestationCertBuf.Length());
86 encoder.write_string("authData");
87 encoder.write_bytes(aAuthDataBuf.Elements(), aAuthDataBuf.Length());
90 if (!aAttestationObj.Assign(cborAttOut.data(), cborAttOut.size())) {
91 return NS_ERROR_OUT_OF_MEMORY;
93 return NS_OK;
96 nsresult CBOREncodeNoneAttestationObj(const CryptoBuffer& aAuthDataBuf,
97 /* out */ CryptoBuffer& aAttestationObj) {
99 Attestation Object, encoded in CBOR (description is CDDL)
101 $$attStmtType //= (
102 fmt: "none",
103 attStmt: emptyMap
106 emptyMap = {}
108 cbor::output_dynamic cborAttOut;
109 cbor::encoder encoder(cborAttOut);
110 encoder.write_map(3);
112 encoder.write_string("fmt");
113 encoder.write_string("none");
115 encoder.write_string("attStmt");
116 encoder.write_map(0);
118 encoder.write_string("authData");
119 encoder.write_bytes(aAuthDataBuf.Elements(), aAuthDataBuf.Length());
122 if (!aAttestationObj.Assign(cborAttOut.data(), cborAttOut.size())) {
123 return NS_ERROR_OUT_OF_MEMORY;
125 return NS_OK;
128 } // namespace mozilla::dom