forked from mirrors/gecko-dev
Bug 1816520 - implement getPublicKey and getPublicKeyAlgorithm for AuthenticatorAttestationResponse. r=keeler,webidl,smaug
Differential Revision: https://phabricator.services.mozilla.com/D186375
This commit is contained in:
parent
eb35827ea1
commit
1e85c0a52b
6 changed files with 80 additions and 6 deletions
|
|
@ -102,4 +102,51 @@ void AuthenticatorAttestationResponse::GetAuthenticatorData(
|
||||||
aValue.set(buffer);
|
aValue.set(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AuthenticatorAttestationResponse::GetPublicKey(
|
||||||
|
JSContext* aCx, JS::MutableHandle<JSObject*> aValue, ErrorResult& aRv) {
|
||||||
|
if (!mAttestationObjectParsed) {
|
||||||
|
nsresult rv = authrs_webauthn_att_obj_constructor(
|
||||||
|
mAttestationObject, false, getter_AddRefs(mAttestationObjectParsed));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
aRv.Throw(rv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<uint8_t> publicKey;
|
||||||
|
nsresult rv = mAttestationObjectParsed->GetPublicKey(publicKey);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||||
|
aValue.set(nullptr);
|
||||||
|
} else {
|
||||||
|
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Heap<JSObject*> buffer(
|
||||||
|
ArrayBuffer::Create(aCx, publicKey.Length(), publicKey.Elements()));
|
||||||
|
if (!buffer) {
|
||||||
|
aRv.NoteJSContextException(aCx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
aValue.set(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
COSEAlgorithmIdentifier AuthenticatorAttestationResponse::GetPublicKeyAlgorithm(
|
||||||
|
ErrorResult& aRv) {
|
||||||
|
if (!mAttestationObjectParsed) {
|
||||||
|
nsresult rv = authrs_webauthn_att_obj_constructor(
|
||||||
|
mAttestationObject, false, getter_AddRefs(mAttestationObjectParsed));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
aRv.Throw(rv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
COSEAlgorithmIdentifier alg;
|
||||||
|
mAttestationObjectParsed->GetPublicKeyAlgorithm(&alg);
|
||||||
|
return alg;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,11 @@ class AuthenticatorAttestationResponse final : public AuthenticatorResponse {
|
||||||
void GetAuthenticatorData(JSContext* aCx, JS::MutableHandle<JSObject*> aValue,
|
void GetAuthenticatorData(JSContext* aCx, JS::MutableHandle<JSObject*> aValue,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
void GetPublicKey(JSContext* aCx, JS::MutableHandle<JSObject*> aValue,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
COSEAlgorithmIdentifier GetPublicKeyAlgorithm(ErrorResult& aRv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsTArray<uint8_t> mAttestationObject;
|
nsTArray<uint8_t> mAttestationObject;
|
||||||
nsCOMPtr<nsIWebAuthnAttObj> mAttestationObjectParsed;
|
nsCOMPtr<nsIWebAuthnAttObj> mAttestationObjectParsed;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ extern crate xpcom;
|
||||||
|
|
||||||
use authenticator::{
|
use authenticator::{
|
||||||
authenticatorservice::{RegisterArgs, SignArgs},
|
authenticatorservice::{RegisterArgs, SignArgs},
|
||||||
|
crypto::COSEKeyType,
|
||||||
ctap2::attestation::AttestationObject,
|
ctap2::attestation::AttestationObject,
|
||||||
ctap2::commands::get_info::AuthenticatorVersion,
|
ctap2::commands::get_info::AuthenticatorVersion,
|
||||||
ctap2::server::{
|
ctap2::server::{
|
||||||
|
|
@ -140,6 +141,28 @@ impl WebAuthnAttObj {
|
||||||
// TODO(https://github.com/mozilla/authenticator-rs/issues/302) use to_writer
|
// TODO(https://github.com/mozilla/authenticator-rs/issues/302) use to_writer
|
||||||
Ok(self.att_obj.auth_data.to_vec().into())
|
Ok(self.att_obj.auth_data.to_vec().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xpcom_method!(get_public_key => GetPublicKey() -> ThinVec<u8>);
|
||||||
|
fn get_public_key(&self) -> Result<ThinVec<u8>, nsresult> {
|
||||||
|
let Some(credential_data) = &self.att_obj.auth_data.credential_data else {
|
||||||
|
return Err(NS_ERROR_FAILURE);
|
||||||
|
};
|
||||||
|
// We only support encoding (some) EC2 keys in DER SPKI format.
|
||||||
|
let COSEKeyType::EC2(ref key) = credential_data.credential_public_key.key else {
|
||||||
|
return Err(NS_ERROR_NOT_AVAILABLE);
|
||||||
|
};
|
||||||
|
Ok(key.der_spki().or(Err(NS_ERROR_NOT_AVAILABLE))?.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
xpcom_method!(get_public_key_algorithm => GetPublicKeyAlgorithm() -> i32);
|
||||||
|
fn get_public_key_algorithm(&self) -> Result<i32, nsresult> {
|
||||||
|
if let Some(credential_data) = &self.att_obj.auth_data.credential_data {
|
||||||
|
// safe to cast to i32 by inspection of defined values
|
||||||
|
Ok(credential_data.credential_public_key.alg as i32)
|
||||||
|
} else {
|
||||||
|
Err(NS_ERROR_FAILURE)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[xpcom(implement(nsICtapSignResult), atomic)]
|
#[xpcom(implement(nsICtapSignResult), atomic)]
|
||||||
|
|
|
||||||
|
|
@ -139,9 +139,9 @@ interface nsIWebAuthnAttObj : nsISupports {
|
||||||
|
|
||||||
readonly attribute Array<octet> authenticatorData;
|
readonly attribute Array<octet> authenticatorData;
|
||||||
|
|
||||||
// Bug 1816520
|
readonly attribute Array<octet> publicKey;
|
||||||
// readonly attribute Array<octet> publicKey
|
|
||||||
// readonly attribute COSEAlgorithmIdentifier publicKeyAlgorithm;
|
readonly attribute COSEAlgorithmIdentifier publicKeyAlgorithm;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The nsICtapSignResult interface is used to construct IPDL-defined
|
// The nsICtapSignResult interface is used to construct IPDL-defined
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ interface AuthenticatorResponse {
|
||||||
interface AuthenticatorAttestationResponse : AuthenticatorResponse {
|
interface AuthenticatorAttestationResponse : AuthenticatorResponse {
|
||||||
[SameObject, Throws] readonly attribute ArrayBuffer attestationObject;
|
[SameObject, Throws] readonly attribute ArrayBuffer attestationObject;
|
||||||
[Throws] ArrayBuffer getAuthenticatorData();
|
[Throws] ArrayBuffer getAuthenticatorData();
|
||||||
|
[Throws] ArrayBuffer? getPublicKey();
|
||||||
|
[Throws] COSEAlgorithmIdentifier getPublicKeyAlgorithm();
|
||||||
};
|
};
|
||||||
|
|
||||||
[SecureContext, Pref="security.webauth.webauthn",
|
[SecureContext, Pref="security.webauth.webauthn",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
[createcredential-getpublickey.https.html]
|
|
||||||
[WebAuthn getPublicKey]
|
|
||||||
expected: FAIL
|
|
||||||
Loading…
Reference in a new issue