• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

google / OpenSK / 4607402897

pending completion
4607402897

push

github

GitHub
Adds a trait for crypto, porting EC first (#606)

290 of 290 new or added lines in 14 files covered. (100.0%)

13256 of 13765 relevant lines covered (96.3%)

5922.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.03
/libraries/opensk/src/api/crypto/software_crypto.rs
1
// Copyright 2023 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
use crate::api::crypto::{ecdh, ecdsa, Crypto, EC_FIELD_SIZE, EC_SIGNATURE_SIZE};
16
use alloc::vec::Vec;
17
use rng256::Rng256;
18

19
pub struct SoftwareCrypto;
20
pub struct SoftwareEcdh;
21
pub struct SoftwareEcdsa;
22

23
impl Crypto for SoftwareCrypto {
24
    type Ecdh = SoftwareEcdh;
25
    type Ecdsa = SoftwareEcdsa;
26
}
27

28
impl ecdh::Ecdh for SoftwareEcdh {
29
    type SecretKey = SoftwareEcdhSecretKey;
30
    type PublicKey = SoftwareEcdhPublicKey;
31
    type SharedSecret = SoftwareEcdhSharedSecret;
32
}
33

34
pub struct SoftwareEcdhSecretKey {
35
    sec_key: crypto::ecdh::SecKey,
36
}
37

38
impl ecdh::SecretKey for SoftwareEcdhSecretKey {
39
    type PublicKey = SoftwareEcdhPublicKey;
40
    type SharedSecret = SoftwareEcdhSharedSecret;
41

42
    fn random(rng: &mut impl Rng256) -> Self {
684✔
43
        let sec_key = crypto::ecdh::SecKey::gensk(rng);
684✔
44
        Self { sec_key }
684✔
45
    }
684✔
46

47
    fn public_key(&self) -> Self::PublicKey {
190✔
48
        let pub_key = self.sec_key.genpk();
190✔
49
        SoftwareEcdhPublicKey { pub_key }
190✔
50
    }
190✔
51

52
    fn diffie_hellman(&self, public_key: &SoftwareEcdhPublicKey) -> Self::SharedSecret {
186✔
53
        let shared_secret = self.sec_key.exchange_x(&public_key.pub_key);
186✔
54
        SoftwareEcdhSharedSecret { shared_secret }
186✔
55
    }
186✔
56
}
57

58
pub struct SoftwareEcdhPublicKey {
59
    pub_key: crypto::ecdh::PubKey,
60
}
61

62
impl ecdh::PublicKey for SoftwareEcdhPublicKey {
63
    fn from_coordinates(x: &[u8; EC_FIELD_SIZE], y: &[u8; EC_FIELD_SIZE]) -> Option<Self> {
186✔
64
        crypto::ecdh::PubKey::from_coordinates(x, y).map(|k| Self { pub_key: k })
279✔
65
    }
186✔
66

67
    fn to_coordinates(&self, x: &mut [u8; EC_FIELD_SIZE], y: &mut [u8; EC_FIELD_SIZE]) {
190✔
68
        self.pub_key.to_coordinates(x, y);
190✔
69
    }
190✔
70
}
71

72
pub struct SoftwareEcdhSharedSecret {
73
    shared_secret: [u8; EC_FIELD_SIZE],
74
}
75

76
impl ecdh::SharedSecret for SoftwareEcdhSharedSecret {
77
    fn raw_secret_bytes(&self) -> [u8; EC_FIELD_SIZE] {
186✔
78
        self.shared_secret
186✔
79
    }
186✔
80
}
81

82
impl ecdsa::Ecdsa for SoftwareEcdsa {
83
    type SecretKey = SoftwareEcdsaSecretKey;
84
    type PublicKey = SoftwareEcdsaPublicKey;
85
    type Signature = SoftwareEcdsaSignature;
86
}
87

88
pub struct SoftwareEcdsaSecretKey {
89
    sec_key: crypto::ecdsa::SecKey,
90
}
91

92
impl ecdsa::SecretKey for SoftwareEcdsaSecretKey {
93
    type PublicKey = SoftwareEcdsaPublicKey;
94
    type Signature = SoftwareEcdsaSignature;
95

96
    fn random(rng: &mut impl Rng256) -> Self {
1,116✔
97
        let sec_key = crypto::ecdsa::SecKey::gensk(rng);
1,116✔
98
        Self { sec_key }
1,116✔
99
    }
1,116✔
100

101
    fn from_slice(bytes: &[u8; EC_FIELD_SIZE]) -> Option<Self> {
538✔
102
        crypto::ecdsa::SecKey::from_bytes(bytes).map(|k| Self { sec_key: k })
807✔
103
    }
538✔
104

105
    fn public_key(&self) -> Self::PublicKey {
112✔
106
        let pub_key = self.sec_key.genpk();
112✔
107
        SoftwareEcdsaPublicKey { pub_key }
112✔
108
    }
112✔
109

110
    fn sign(&self, message: &[u8]) -> Self::Signature {
158✔
111
        let signature = self.sec_key.sign_rfc6979::<crypto::sha256::Sha256>(message);
158✔
112
        SoftwareEcdsaSignature { signature }
158✔
113
    }
158✔
114

115
    fn to_slice(&self, bytes: &mut [u8; EC_FIELD_SIZE]) {
1,116✔
116
        self.sec_key.to_bytes(bytes);
1,116✔
117
    }
1,116✔
118
}
119

120
pub struct SoftwareEcdsaPublicKey {
121
    pub_key: crypto::ecdsa::PubKey,
122
}
123

124
impl ecdsa::PublicKey for SoftwareEcdsaPublicKey {
125
    type Signature = SoftwareEcdsaSignature;
126

127
    fn from_coordinates(x: &[u8; EC_FIELD_SIZE], y: &[u8; EC_FIELD_SIZE]) -> Option<Self> {
2✔
128
        crypto::ecdsa::PubKey::from_coordinates(x, y).map(|k| Self { pub_key: k })
3✔
129
    }
2✔
130

131
    fn verify(&self, message: &[u8], signature: &Self::Signature) -> bool {
2✔
132
        self.pub_key
2✔
133
            .verify_vartime::<crypto::sha256::Sha256>(message, &signature.signature)
2✔
134
    }
2✔
135

136
    fn to_coordinates(&self, x: &mut [u8; EC_FIELD_SIZE], y: &mut [u8; EC_FIELD_SIZE]) {
110✔
137
        self.pub_key.to_coordinates(x, y);
110✔
138
    }
110✔
139
}
140

141
pub struct SoftwareEcdsaSignature {
142
    signature: crypto::ecdsa::Signature,
143
}
144

145
impl ecdsa::Signature for SoftwareEcdsaSignature {
146
    fn from_slice(bytes: &[u8; EC_SIGNATURE_SIZE]) -> Option<Self> {
×
147
        crypto::ecdsa::Signature::from_bytes(bytes).map(|s| SoftwareEcdsaSignature { signature: s })
×
148
    }
×
149

150
    fn to_der(&self) -> Vec<u8> {
156✔
151
        self.signature.to_asn1_der()
156✔
152
    }
156✔
153
}
154

155
#[cfg(test)]
156
mod test {
157
    use super::*;
158
    use crate::api::crypto::ecdh::{
159
        PublicKey as EcdhPublicKey, SecretKey as EcdhSecretKey, SharedSecret,
160
    };
161
    use crate::api::crypto::ecdsa::{PublicKey as EcdsaPublicKey, SecretKey as EcdsaSecretKey};
162
    use crate::env::test::TestEnv;
163

164
    #[test]
2✔
165
    fn test_shared_secret_symmetric() {
2✔
166
        let mut env = TestEnv::default();
2✔
167
        let private1 = SoftwareEcdhSecretKey::random(env.rng());
2✔
168
        let private2 = SoftwareEcdhSecretKey::random(env.rng());
2✔
169
        let pub1 = private1.public_key();
2✔
170
        let pub2 = private2.public_key();
2✔
171
        let shared1 = private1.diffie_hellman(&pub2);
2✔
172
        let shared2 = private2.diffie_hellman(&pub1);
2✔
173
        assert_eq!(shared1.raw_secret_bytes(), shared2.raw_secret_bytes());
2✔
174
    }
2✔
175

176
    #[test]
2✔
177
    fn test_ecdh_public_key_from_to_bytes() {
2✔
178
        let mut env = TestEnv::default();
2✔
179
        let first_key = SoftwareEcdhSecretKey::random(env.rng());
2✔
180
        let first_public = first_key.public_key();
2✔
181
        let mut x = [0; EC_FIELD_SIZE];
2✔
182
        let mut y = [0; EC_FIELD_SIZE];
2✔
183
        first_public.to_coordinates(&mut x, &mut y);
2✔
184
        let new_public = SoftwareEcdhPublicKey::from_coordinates(&x, &y).unwrap();
2✔
185
        let mut new_x = [0; EC_FIELD_SIZE];
2✔
186
        let mut new_y = [0; EC_FIELD_SIZE];
2✔
187
        new_public.to_coordinates(&mut new_x, &mut new_y);
2✔
188
        assert_eq!(x, new_x);
2✔
189
        assert_eq!(y, new_y);
2✔
190
    }
2✔
191

192
    #[test]
2✔
193
    fn test_sign_verify() {
2✔
194
        let mut env = TestEnv::default();
2✔
195
        let private_key = SoftwareEcdsaSecretKey::random(env.rng());
2✔
196
        let public_key = private_key.public_key();
2✔
197
        let message = [0x12, 0x34, 0x56, 0x78];
2✔
198
        let signature = private_key.sign(&message);
2✔
199
        assert!(public_key.verify(&message, &signature));
2✔
200
    }
2✔
201

202
    #[test]
2✔
203
    fn test_ecdsa_secret_key_from_to_bytes() {
2✔
204
        let mut env = TestEnv::default();
2✔
205
        let first_key = SoftwareEcdsaSecretKey::random(env.rng());
2✔
206
        let mut key_bytes = [0; EC_FIELD_SIZE];
2✔
207
        first_key.to_slice(&mut key_bytes);
2✔
208
        let second_key = SoftwareEcdsaSecretKey::from_slice(&key_bytes).unwrap();
2✔
209
        let mut new_bytes = [0; EC_FIELD_SIZE];
2✔
210
        second_key.to_slice(&mut new_bytes);
2✔
211
        assert_eq!(key_bytes, new_bytes);
2✔
212
    }
2✔
213
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc