44
55#include "sw/device/lib/crypto/include/rsa.h"
66
7+ #include "sw/device/lib/base/math.h"
78#include "sw/device/lib/base/memory.h"
89#include "sw/device/lib/base/status.h"
910#include "sw/device/lib/crypto/impl/integrity.h"
2728 */
2829 kCryptotestRsaPaddingPkcs = 0 ,
2930 kCryptotestRsaPaddingPss = 1 ,
31+ kCryptotestRsaPaddingOaep = 2 ,
3032 /**
3133 * Number of words for different RSA modes.
3234 */
@@ -49,6 +51,181 @@ enum {
4951 kCryptotestRsaShake256 = 7 ,
5052};
5153
54+ status_t handle_rsa_decrypt (ujson_t * uj ) {
55+ cryptotest_rsa_decrypt_t uj_input ;
56+ TRY (ujson_deserialize_cryptotest_rsa_decrypt_t (uj , & uj_input ));
57+
58+ if (uj_input .padding != kCryptotestRsaPaddingOaep ) {
59+ LOG_ERROR ("Unsupported RSA padding: %d" , uj_input .padding );
60+ return INVALID_ARGUMENT ();
61+ }
62+
63+ if (uj_input .e != kCryptotestRsaSupportedE ) {
64+ LOG_ERROR ("Unsupported RSA public exponent e: %d" , uj_input .e );
65+ return INVALID_ARGUMENT ();
66+ }
67+
68+ size_t rsa_num_words ;
69+ size_t private_key_bytes ;
70+ size_t private_key_blob_bytes ;
71+ otcrypto_rsa_size_t rsa_size ;
72+ size_t n_bytes = uj_input .security_level / 8 ;
73+ switch (n_bytes ) {
74+ case kOtcryptoRsa2048PublicKeyBytes :
75+ rsa_size = kOtcryptoRsaSize2048 ;
76+ rsa_num_words = kCryptotestRsa2048NumWords ;
77+ private_key_bytes = kOtcryptoRsa2048PrivateKeyBytes ;
78+ private_key_blob_bytes = kOtcryptoRsa2048PrivateKeyblobBytes ;
79+ break ;
80+ case kOtcryptoRsa3072PublicKeyBytes :
81+ rsa_size = kOtcryptoRsaSize3072 ;
82+ rsa_num_words = kCryptotestRsa3072NumWords ;
83+ private_key_bytes = kOtcryptoRsa3072PrivateKeyBytes ;
84+ private_key_blob_bytes = kOtcryptoRsa3072PrivateKeyblobBytes ;
85+ break ;
86+ case kOtcryptoRsa4096PublicKeyBytes :
87+ rsa_size = kOtcryptoRsaSize4096 ;
88+ rsa_num_words = kCryptotestRsa4096NumWords ;
89+ private_key_bytes = kOtcryptoRsa4096PrivateKeyBytes ;
90+ private_key_blob_bytes = kOtcryptoRsa4096PrivateKeyblobBytes ;
91+ break ;
92+ default :
93+ LOG_ERROR ("Unsupported RSA security_level: %d" , uj_input .security_level );
94+ return INVALID_ARGUMENT ();
95+ }
96+
97+ otcrypto_hash_mode_t hash_mode ;
98+ size_t hash_digest_bytes ;
99+ switch (uj_input .hashing ) {
100+ case kCryptotestRsaSha256 :
101+ hash_mode = kOtcryptoHashModeSha256 ;
102+ hash_digest_bytes = 256 / 8 ;
103+ break ;
104+ case kCryptotestRsaSha384 :
105+ hash_mode = kOtcryptoHashModeSha384 ;
106+ hash_digest_bytes = 384 / 8 ;
107+ break ;
108+ case kCryptotestRsaSha512 :
109+ hash_mode = kOtcryptoHashModeSha512 ;
110+ hash_digest_bytes = 512 / 8 ;
111+ break ;
112+ case kCryptotestRsaSha3_256 :
113+ hash_mode = kOtcryptoHashModeSha3_256 ;
114+ hash_digest_bytes = 256 / 8 ;
115+ break ;
116+ case kCryptotestRsaSha3_384 :
117+ hash_mode = kOtcryptoHashModeSha3_384 ;
118+ hash_digest_bytes = 384 / 8 ;
119+ break ;
120+ case kCryptotestRsaSha3_512 :
121+ hash_mode = kOtcryptoHashModeSha3_512 ;
122+ hash_digest_bytes = 512 / 8 ;
123+ break ;
124+ case kCryptotestRsaShake128 :
125+ hash_mode = kOtcryptoHashXofModeShake128 ;
126+ hash_digest_bytes = 128 / 8 ;
127+ break ;
128+ case kCryptotestRsaShake256 :
129+ hash_mode = kOtcryptoHashXofModeShake256 ;
130+ hash_digest_bytes = 256 / 8 ;
131+ break ;
132+ default :
133+ LOG_ERROR ("Unsupported RSA hash mode: %d" , uj_input .hashing );
134+ return INVALID_ARGUMENT ();
135+ }
136+
137+ // Create the modulus N buffer.
138+ uint32_t n_buf [rsa_num_words ];
139+ memset (n_buf , 0 , sizeof (n_buf ));
140+ memcpy (n_buf , uj_input .n , n_bytes );
141+
142+ otcrypto_const_word32_buf_t modulus = {
143+ .data = n_buf ,
144+ .len = rsa_num_words ,
145+ };
146+
147+ // Create two shares for the private exponent (second share is all-zero).
148+ uint32_t d_buf [rsa_num_words ];
149+ memset (d_buf , 0 , sizeof (d_buf ));
150+ memcpy (d_buf , uj_input .d , n_bytes );
151+ otcrypto_const_word32_buf_t d_share0 = {
152+ .data = d_buf ,
153+ .len = rsa_num_words ,
154+ };
155+
156+ uint32_t share1 [rsa_num_words ];
157+ memset (share1 , 0 , sizeof (share1 ));
158+ otcrypto_const_word32_buf_t d_share1 = {
159+ .data = share1 ,
160+ .len = rsa_num_words ,
161+ };
162+
163+ // Construct the private key.
164+ otcrypto_key_config_t private_key_config = {
165+ .version = kOtcryptoLibVersion1 ,
166+ .key_mode = kOtcryptoKeyModeRsaEncryptOaep ,
167+ .key_length = private_key_bytes ,
168+ .hw_backed = kHardenedBoolFalse ,
169+ .security_level = kOtcryptoKeySecurityLevelLow ,
170+ };
171+
172+ size_t keyblob_words = ceil_div (private_key_blob_bytes , sizeof (uint32_t ));
173+ uint32_t keyblob [keyblob_words ];
174+ otcrypto_blinded_key_t private_key = {
175+ .config = private_key_config ,
176+ .keyblob = keyblob ,
177+ .keyblob_length = private_key_blob_bytes ,
178+ };
179+
180+ TRY (otcrypto_rsa_private_key_from_exponents (rsa_size , modulus , d_share0 ,
181+ d_share1 , & private_key ));
182+
183+ uint32_t ciphertext_buf [rsa_num_words ];
184+ memset (ciphertext_buf , 0 , sizeof (ciphertext_buf ));
185+ memcpy (ciphertext_buf , uj_input .ciphertext , uj_input .ciphertext_len );
186+
187+ otcrypto_const_word32_buf_t ciphertext = {
188+ .len = rsa_num_words ,
189+ .data = ciphertext_buf ,
190+ };
191+
192+ // Create label.
193+ uint8_t label_buf [uj_input .label_len ];
194+ memset (label_buf , 0 , sizeof (label_buf ));
195+ memcpy (label_buf , uj_input .label , uj_input .label_len );
196+ otcrypto_const_byte_buf_t label = {
197+ .data = label_buf ,
198+ .len = uj_input .label_len ,
199+ };
200+
201+ // Create output buffer for the plaintext.
202+ // Maximum plaintext length for OAEP (see IETF RFC 8017).
203+ size_t kMaxPlaintextBytes = n_bytes - 2 * hash_digest_bytes - 2 ;
204+ uint8_t plaintext_buf [kMaxPlaintextBytes ];
205+ otcrypto_byte_buf_t plaintext = {
206+ .data = plaintext_buf ,
207+ .len = kMaxPlaintextBytes ,
208+ };
209+
210+ size_t msg_len ;
211+ bool status_resp = true;
212+ otcrypto_status_t status = otcrypto_rsa_decrypt (
213+ & private_key , hash_mode , ciphertext , label , plaintext , & msg_len );
214+ if (status .value != kOtcryptoStatusValueOk ) {
215+ status_resp = false;
216+ }
217+
218+ // Return plaintext and the status back to host.
219+ cryptotest_rsa_decrypt_resp_t uj_output ;
220+ memset (uj_output .plaintext , 0 , RSA_CMD_MAX_MESSAGE_BYTES );
221+ memcpy (uj_output .plaintext , plaintext_buf , msg_len );
222+ uj_output .plaintext_len = msg_len ;
223+ uj_output .result = status_resp ;
224+
225+ RESP_OK (ujson_serialize_cryptotest_rsa_decrypt_resp_t , uj , & uj_output );
226+ return OK_STATUS ();
227+ }
228+
52229status_t handle_rsa_verify (ujson_t * uj ) {
53230 cryptotest_rsa_verify_t uj_input ;
54231 TRY (ujson_deserialize_cryptotest_rsa_verify_t (uj , & uj_input ));
@@ -231,6 +408,8 @@ status_t handle_rsa(ujson_t *uj) {
231408 rsa_subcommand_t cmd ;
232409 TRY (ujson_deserialize_rsa_subcommand_t (uj , & cmd ));
233410 switch (cmd ) {
411+ case kRsaSubcommandRsaDecrypt :
412+ return handle_rsa_decrypt (uj );
234413 case kRsaSubcommandRsaVerify :
235414 return handle_rsa_verify (uj );
236415 default :
0 commit comments