2
2
// SPDX-License-Identifier: Apache-2.0
3
3
use super :: utils;
4
4
use super :: utils:: PasswordContext ;
5
+ use super :: utils:: { validate_private_key, validate_public_key} ;
5
6
use super :: TpmProvider ;
6
7
use crate :: authenticators:: ApplicationName ;
7
8
use crate :: key_info_managers;
@@ -14,10 +15,10 @@ use parsec_interface::operations::{
14
15
} ;
15
16
use parsec_interface:: requests:: { ProviderID , ResponseStatus , Result } ;
16
17
use parsec_interface:: secrecy:: ExposeSecret ;
17
- use picky_asn1_x509:: RSAPublicKey ;
18
+ use picky_asn1_x509:: { RSAPrivateKey , RSAPublicKey } ;
19
+ use std:: convert:: TryInto ;
20
+ use tss_esapi:: abstraction:: transient:: RsaExponent ;
18
21
19
- // Public exponent value for all RSA keys.
20
- const PUBLIC_EXPONENT : [ u8 ; 3 ] = [ 0x01 , 0x00 , 0x01 ] ;
21
22
const AUTH_VAL_LEN : usize = 32 ;
22
23
23
24
// Inserts a new mapping in the Key Info manager that stores the PasswordContext.
@@ -116,6 +117,7 @@ impl TpmProvider {
116
117
) -> Result < psa_import_key:: Result > {
117
118
match op. attributes . key_type {
118
119
Type :: RsaPublicKey => self . psa_import_key_internal_rsa_public ( app_name, op) ,
120
+ Type :: RsaKeyPair => self . psa_import_key_internal_rsa_keypair ( app_name, op) ,
119
121
_ => {
120
122
error ! (
121
123
"The TPM provider does not support the {:?} key type." ,
@@ -151,50 +153,9 @@ impl TpmProvider {
151
153
ResponseStatus :: PsaErrorInvalidArgument
152
154
} ) ?;
153
155
154
- if public_key. modulus . is_negative ( ) || public_key. public_exponent . is_negative ( ) {
155
- error ! ( "Only positive modulus and public exponent are supported." ) ;
156
- return Err ( ResponseStatus :: PsaErrorInvalidArgument ) ;
157
- }
156
+ validate_public_key ( & public_key, & attributes) ?;
158
157
159
- if public_key. public_exponent . as_unsigned_bytes_be ( ) != PUBLIC_EXPONENT {
160
- if crate :: utils:: GlobalConfig :: log_error_details ( ) {
161
- error ! ( "The TPM Provider only supports 0x101 as public exponent for RSA public keys, {:?} given." , public_key. public_exponent. as_unsigned_bytes_be( ) ) ;
162
- } else {
163
- error ! (
164
- "The TPM Provider only supports 0x101 as public exponent for RSA public keys"
165
- ) ;
166
- }
167
- return Err ( ResponseStatus :: PsaErrorNotSupported ) ;
168
- }
169
158
let key_data = public_key. modulus . as_unsigned_bytes_be ( ) ;
170
- let len = key_data. len ( ) ;
171
-
172
- let key_bits = attributes. bits ;
173
- if key_bits != 0 && len * 8 != key_bits {
174
- if crate :: utils:: GlobalConfig :: log_error_details ( ) {
175
- error ! (
176
- "`bits` field of key attributes (value: {}) must be either 0 or equal to the size of the key in `data` (value: {})." ,
177
- attributes. bits,
178
- len * 8
179
- ) ;
180
- } else {
181
- error ! ( "`bits` field of key attributes must be either 0 or equal to the size of the key in `data`." ) ;
182
- }
183
- return Err ( ResponseStatus :: PsaErrorInvalidArgument ) ;
184
- }
185
-
186
- if len != 128 && len != 256 {
187
- if crate :: utils:: GlobalConfig :: log_error_details ( ) {
188
- error ! (
189
- "The TPM provider only supports 1024 and 2048 bits RSA public keys ({} bits given)." ,
190
- len * 8
191
- ) ;
192
- } else {
193
- error ! ( "The TPM provider only supports 1024 and 2048 bits RSA public keys" ) ;
194
- }
195
- return Err ( ResponseStatus :: PsaErrorNotSupported ) ;
196
- }
197
-
198
159
let pub_key_context = esapi_context
199
160
. load_external_rsa_public_key ( & key_data)
200
161
. map_err ( |e| {
@@ -215,6 +176,77 @@ impl TpmProvider {
215
176
Ok ( psa_import_key:: Result { } )
216
177
}
217
178
179
+ pub ( super ) fn psa_import_key_internal_rsa_keypair (
180
+ & self ,
181
+ app_name : ApplicationName ,
182
+ op : psa_import_key:: Operation ,
183
+ ) -> Result < psa_import_key:: Result > {
184
+ let key_name = op. key_name ;
185
+ let attributes = op. attributes ;
186
+ let key_triple = KeyTriple :: new ( app_name, ProviderID :: Tpm , key_name) ;
187
+ let key_data = op. data ;
188
+
189
+ let mut store_handle = self
190
+ . key_info_store
191
+ . write ( )
192
+ . expect ( "Key store lock poisoned" ) ;
193
+ let mut esapi_context = self
194
+ . esapi_context
195
+ . lock ( )
196
+ . expect ( "ESAPI Context lock poisoned" ) ;
197
+
198
+ let private_key: RSAPrivateKey = picky_asn1_der:: from_bytes ( key_data. expose_secret ( ) )
199
+ . map_err ( |err| {
200
+ format_error ! ( "Could not deserialise key elements" , err) ;
201
+ ResponseStatus :: PsaErrorInvalidArgument
202
+ } ) ?;
203
+
204
+ // Derive the public key from the keypair.
205
+ let public_key = RSAPublicKey {
206
+ modulus : private_key. modulus ( ) . clone ( ) ,
207
+ public_exponent : private_key. public_exponent ( ) . clone ( ) ,
208
+ } ;
209
+
210
+ // Validate the public and the private key.
211
+ validate_public_key ( & public_key, & attributes) ?;
212
+ validate_private_key ( & private_key, & attributes) ?;
213
+
214
+ let key_prime = private_key. primes ( ) [ 0 ] . as_unsigned_bytes_be ( ) ;
215
+ let public_modulus = private_key. modulus ( ) . as_unsigned_bytes_be ( ) ;
216
+
217
+ let ( int_bytes, _) = private_key
218
+ . public_exponent ( )
219
+ . split_at ( std:: mem:: size_of :: < u32 > ( ) ) ;
220
+ let int_bytes: [ u8 ; 4 ] = int_bytes. try_into ( ) . map_err ( |err| {
221
+ format_error ! ( "Could not convert public exponent into u32" , err) ;
222
+ ResponseStatus :: PsaErrorInvalidArgument
223
+ } ) ?;
224
+
225
+ let public_exponent_u32 = u32:: from_be_bytes ( int_bytes) ;
226
+ let keypair_context = esapi_context
227
+ . load_external_rsa (
228
+ key_prime,
229
+ public_modulus,
230
+ RsaExponent :: new ( public_exponent_u32) ,
231
+ )
232
+ . map_err ( |e| {
233
+ format_error ! ( "Error creating a RSA signing key" , e) ;
234
+ utils:: to_response_status ( e)
235
+ } ) ?;
236
+
237
+ insert_password_context (
238
+ & mut * store_handle,
239
+ key_triple,
240
+ PasswordContext {
241
+ context : keypair_context,
242
+ auth_value : Vec :: new ( ) ,
243
+ } ,
244
+ attributes,
245
+ ) ?;
246
+
247
+ Ok ( psa_import_key:: Result { } )
248
+ }
249
+
218
250
pub ( super ) fn psa_export_public_key_internal (
219
251
& self ,
220
252
app_name : ApplicationName ,
0 commit comments