script/dom/subtlecrypto/
ec_common.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use js::context::JSContext;
6
7use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{KeyType, KeyUsage};
8use crate::dom::bindings::error::Error;
9use crate::dom::bindings::root::DomRoot;
10use crate::dom::cryptokey::{CryptoKey, Handle};
11use crate::dom::globalscope::GlobalScope;
12use crate::dom::subtlecrypto::KeyAlgorithmAndDerivatives;
13
14/// <https://wicg.github.io/webcrypto-modern-algos/#SubtleCrypto-method-getPublicKey>
15/// Step 9 - 15, for elliptic curve cryptography
16pub(crate) fn get_public_key(
17    cx: &mut JSContext,
18    global: &GlobalScope,
19    key: &CryptoKey,
20    algorithm: &KeyAlgorithmAndDerivatives,
21    usages: Vec<KeyUsage>,
22) -> Result<DomRoot<CryptoKey>, Error> {
23    // Step 9. If usages contains an entry which is not supported for a public key by the algorithm
24    // identified by algorithm, then throw a SyntaxError.
25    //
26    // NOTE: See "importKey" operation for supported usages
27    if usages.iter().any(|usage| *usage != KeyUsage::Verify) {
28        return Err(Error::Syntax(Some(
29            "Usages contains an entry which is not \"verify\"".to_string(),
30        )));
31    }
32
33    // Step 10. Let publicKey be a new CryptoKey representing the public key corresponding to the
34    // private key represented by the [[handle]] internal slot of key.
35    // Step 11. If an error occurred, then throw a OperationError.
36    // Step 12. Set the [[type]] internal slot of publicKey to "public".
37    // Step 13. Set the [[algorithm]] internal slot of publicKey to algorithm.
38    // Step 14. Set the [[extractable]] internal slot of publicKey to true.
39    // Step 15. Set the [[usages]] internal slot of publicKey to usages.
40    let public_key_handle = match key.handle() {
41        Handle::P256PrivateKey(private_key) => Handle::P256PublicKey(private_key.public_key()),
42        Handle::P384PrivateKey(private_key) => Handle::P384PublicKey(private_key.public_key()),
43        Handle::P521PrivateKey(private_key) => Handle::P521PublicKey(private_key.public_key()),
44        _ => {
45            return Err(Error::Operation(Some(
46                "[[handle]] internal slot of key is not an elliptic curve private key".to_string(),
47            )));
48        },
49    };
50    let public_key = CryptoKey::new(
51        cx,
52        global,
53        KeyType::Public,
54        true,
55        algorithm.clone(),
56        usages,
57        public_key_handle,
58    );
59
60    Ok(public_key)
61}