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, PUBLIC_EXPONENT } ;
5
6
use super :: TpmProvider ;
6
7
use crate :: authenticators:: ApplicationName ;
7
8
use crate :: key_info_managers;
@@ -14,11 +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 tss_esapi:: abstraction:: transient:: RsaExponent ;
18
20
use zeroize:: Zeroize ;
19
21
20
- // Public exponent value for all RSA keys.
21
- const PUBLIC_EXPONENT : [ u8 ; 3 ] = [ 0x01 , 0x00 , 0x01 ] ;
22
22
const AUTH_VAL_LEN : usize = 32 ;
23
23
24
24
// Inserts a new mapping in the Key Info manager that stores the PasswordContext.
@@ -117,11 +117,24 @@ impl TpmProvider {
117
117
app_name : ApplicationName ,
118
118
op : psa_import_key:: Operation ,
119
119
) -> Result < psa_import_key:: Result > {
120
- if op. attributes . key_type != Type :: RsaPublicKey {
121
- error ! ( "The TPM provider currently only supports importing RSA public key." ) ;
122
- return Err ( ResponseStatus :: PsaErrorNotSupported ) ;
120
+ match op. attributes . key_type {
121
+ Type :: RsaPublicKey => self . psa_import_key_internal_rsa_public ( app_name, op) ,
122
+ Type :: RsaKeyPair => self . psa_import_key_internal_rsa_keypair ( app_name, op) ,
123
+ _ => {
124
+ error ! (
125
+ "The TPM provider does not support importing for the {:?} key type." ,
126
+ op. attributes. key_type
127
+ ) ;
128
+ Err ( ResponseStatus :: PsaErrorNotSupported )
129
+ }
123
130
}
131
+ }
124
132
133
+ pub ( super ) fn psa_import_key_internal_rsa_public (
134
+ & self ,
135
+ app_name : ApplicationName ,
136
+ op : psa_import_key:: Operation ,
137
+ ) -> Result < psa_import_key:: Result > {
125
138
let key_name = op. key_name ;
126
139
let attributes = op. attributes ;
127
140
let key_triple = KeyTriple :: new ( app_name, ProviderID :: Tpm , key_name) ;
@@ -142,50 +155,9 @@ impl TpmProvider {
142
155
ResponseStatus :: PsaErrorInvalidArgument
143
156
} ) ?;
144
157
145
- if public_key. modulus . is_negative ( ) || public_key. public_exponent . is_negative ( ) {
146
- error ! ( "Only positive modulus and public exponent are supported." ) ;
147
- return Err ( ResponseStatus :: PsaErrorInvalidArgument ) ;
148
- }
158
+ validate_public_key ( & public_key, & attributes) ?;
149
159
150
- if public_key. public_exponent . as_unsigned_bytes_be ( ) != PUBLIC_EXPONENT {
151
- if crate :: utils:: GlobalConfig :: log_error_details ( ) {
152
- error ! ( "The TPM Provider only supports 0x101 as public exponent for RSA public keys, {:?} given." , public_key. public_exponent. as_unsigned_bytes_be( ) ) ;
153
- } else {
154
- error ! (
155
- "The TPM Provider only supports 0x101 as public exponent for RSA public keys"
156
- ) ;
157
- }
158
- return Err ( ResponseStatus :: PsaErrorNotSupported ) ;
159
- }
160
160
let key_data = public_key. modulus . as_unsigned_bytes_be ( ) ;
161
- let len = key_data. len ( ) ;
162
-
163
- let key_bits = attributes. bits ;
164
- if key_bits != 0 && len * 8 != key_bits {
165
- if crate :: utils:: GlobalConfig :: log_error_details ( ) {
166
- error ! (
167
- "`bits` field of key attributes (value: {}) must be either 0 or equal to the size of the key in `data` (value: {})." ,
168
- attributes. bits,
169
- len * 8
170
- ) ;
171
- } else {
172
- error ! ( "`bits` field of key attributes must be either 0 or equal to the size of the key in `data`." ) ;
173
- }
174
- return Err ( ResponseStatus :: PsaErrorInvalidArgument ) ;
175
- }
176
-
177
- if len != 128 && len != 256 {
178
- if crate :: utils:: GlobalConfig :: log_error_details ( ) {
179
- error ! (
180
- "The TPM provider only supports 1024 and 2048 bits RSA public keys ({} bits given)." ,
181
- len * 8
182
- ) ;
183
- } else {
184
- error ! ( "The TPM provider only supports 1024 and 2048 bits RSA public keys" ) ;
185
- }
186
- return Err ( ResponseStatus :: PsaErrorNotSupported ) ;
187
- }
188
-
189
161
let pub_key_context = esapi_context
190
162
. load_external_rsa_public_key ( & key_data)
191
163
. map_err ( |e| {
@@ -206,6 +178,64 @@ impl TpmProvider {
206
178
Ok ( psa_import_key:: Result { } )
207
179
}
208
180
181
+ pub ( super ) fn psa_import_key_internal_rsa_keypair (
182
+ & self ,
183
+ app_name : ApplicationName ,
184
+ op : psa_import_key:: Operation ,
185
+ ) -> Result < psa_import_key:: Result > {
186
+ let key_name = op. key_name ;
187
+ let attributes = op. attributes ;
188
+ let key_triple = KeyTriple :: new ( app_name, ProviderID :: Tpm , key_name) ;
189
+ let key_data = op. data ;
190
+
191
+ let mut store_handle = self
192
+ . key_info_store
193
+ . write ( )
194
+ . expect ( "Key store lock poisoned" ) ;
195
+ let mut esapi_context = self
196
+ . esapi_context
197
+ . lock ( )
198
+ . expect ( "ESAPI Context lock poisoned" ) ;
199
+
200
+ let private_key: RSAPrivateKey = picky_asn1_der:: from_bytes ( key_data. expose_secret ( ) )
201
+ . map_err ( |err| {
202
+ format_error ! ( "Could not deserialise key elements" , err) ;
203
+ ResponseStatus :: PsaErrorInvalidArgument
204
+ } ) ?;
205
+
206
+ // Derive the public key from the keypair.
207
+ let public_key = RSAPublicKey {
208
+ modulus : private_key. modulus . clone ( ) ,
209
+ public_exponent : private_key. public_exponent . clone ( ) ,
210
+ } ;
211
+
212
+ // Validate the public and the private key.
213
+ validate_public_key ( & public_key, & attributes) ?;
214
+ validate_private_key ( & private_key, & attributes) ?;
215
+
216
+ let key_prime = private_key. prime_1 . as_unsigned_bytes_be ( ) ;
217
+ let public_modulus = private_key. modulus . as_unsigned_bytes_be ( ) ;
218
+
219
+ let keypair_context = esapi_context
220
+ . load_external_rsa ( key_prime, public_modulus, RsaExponent :: new ( PUBLIC_EXPONENT ) )
221
+ . map_err ( |e| {
222
+ format_error ! ( "Error creating a RSA signing key" , e) ;
223
+ utils:: to_response_status ( e)
224
+ } ) ?;
225
+
226
+ insert_password_context (
227
+ & mut * store_handle,
228
+ key_triple,
229
+ PasswordContext {
230
+ context : keypair_context,
231
+ auth_value : Vec :: new ( ) ,
232
+ } ,
233
+ attributes,
234
+ ) ?;
235
+
236
+ Ok ( psa_import_key:: Result { } )
237
+ }
238
+
209
239
pub ( super ) fn psa_export_public_key_internal (
210
240
& self ,
211
241
app_name : ApplicationName ,
0 commit comments