@@ -51,6 +51,140 @@ enum {
5151 kCryptotestRsaShake256 = 7 ,
5252};
5353
54+ status_t handle_rsa_encrypt (ujson_t * uj ) {
55+ cryptotest_rsa_encrypt_t uj_input ;
56+ TRY (ujson_deserialize_cryptotest_rsa_encrypt_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 public_key_bytes ;
70+ otcrypto_rsa_size_t rsa_size ;
71+ size_t n_bytes = uj_input .security_level / 8 ;
72+ switch (n_bytes ) {
73+ case kOtcryptoRsa2048PublicKeyBytes :
74+ rsa_size = kOtcryptoRsaSize2048 ;
75+ rsa_num_words = kCryptotestRsa2048NumWords ;
76+ public_key_bytes = kOtcryptoRsa2048PublicKeyBytes ;
77+ break ;
78+ case kOtcryptoRsa3072PublicKeyBytes :
79+ rsa_size = kOtcryptoRsaSize3072 ;
80+ rsa_num_words = kCryptotestRsa3072NumWords ;
81+ public_key_bytes = kOtcryptoRsa3072PublicKeyBytes ;
82+ break ;
83+ case kOtcryptoRsa4096PublicKeyBytes :
84+ rsa_size = kOtcryptoRsaSize4096 ;
85+ rsa_num_words = kCryptotestRsa4096NumWords ;
86+ public_key_bytes = kOtcryptoRsa4096PublicKeyBytes ;
87+ break ;
88+ default :
89+ LOG_ERROR ("Unsupported RSA security_level: %d" , uj_input .security_level );
90+ return INVALID_ARGUMENT ();
91+ }
92+
93+ otcrypto_hash_mode_t hash_mode ;
94+ switch (uj_input .hashing ) {
95+ case kCryptotestRsaSha256 :
96+ hash_mode = kOtcryptoHashModeSha256 ;
97+ break ;
98+ case kCryptotestRsaSha384 :
99+ hash_mode = kOtcryptoHashModeSha384 ;
100+ break ;
101+ case kCryptotestRsaSha512 :
102+ hash_mode = kOtcryptoHashModeSha512 ;
103+ break ;
104+ case kCryptotestRsaSha3_256 :
105+ hash_mode = kOtcryptoHashModeSha3_256 ;
106+ break ;
107+ case kCryptotestRsaSha3_384 :
108+ hash_mode = kOtcryptoHashModeSha3_384 ;
109+ break ;
110+ case kCryptotestRsaSha3_512 :
111+ hash_mode = kOtcryptoHashModeSha3_512 ;
112+ break ;
113+ case kCryptotestRsaShake128 :
114+ hash_mode = kOtcryptoHashXofModeShake128 ;
115+ break ;
116+ case kCryptotestRsaShake256 :
117+ hash_mode = kOtcryptoHashXofModeShake256 ;
118+ break ;
119+ default :
120+ LOG_ERROR ("Unsupported RSA hash mode: %d" , uj_input .hashing );
121+ return INVALID_ARGUMENT ();
122+ }
123+
124+ // Create the modulus N buffer.
125+ uint32_t n_buf [rsa_num_words ];
126+ memset (n_buf , 0 , sizeof (n_buf ));
127+ memcpy (n_buf , uj_input .n , n_bytes );
128+
129+ otcrypto_const_word32_buf_t modulus = {
130+ .data = n_buf ,
131+ .len = rsa_num_words ,
132+ };
133+
134+ // Construct the public key.
135+ uint32_t public_key_data [ceil_div (public_key_bytes , sizeof (uint32_t ))];
136+
137+ otcrypto_unblinded_key_t public_key = {
138+ .key_mode = kOtcryptoKeyModeRsaEncryptOaep ,
139+ .key_length = public_key_bytes ,
140+ .key = public_key_data ,
141+ };
142+
143+ TRY (otcrypto_rsa_public_key_construct (rsa_size , modulus , & public_key ));
144+
145+ // Create input message.
146+ uint8_t msg_buf [rsa_num_words ];
147+ memset (msg_buf , 0 , sizeof (msg_buf ));
148+ memcpy (msg_buf , uj_input .plaintext , uj_input .plaintext_len );
149+ otcrypto_const_byte_buf_t input_message = {
150+ .len = uj_input .plaintext_len ,
151+ .data = msg_buf ,
152+ };
153+
154+ // Create label.
155+ uint8_t label_buf [uj_input .label_len ];
156+ memset (label_buf , 0 , sizeof (label_buf ));
157+ memcpy (label_buf , uj_input .label , uj_input .label_len );
158+ otcrypto_const_byte_buf_t label = {
159+ .data = label_buf ,
160+ .len = uj_input .label_len ,
161+ };
162+
163+ // Output buffer.
164+ uint32_t ciphertext_buf [rsa_num_words ];
165+ otcrypto_word32_buf_t ciphertext = {
166+ .data = ciphertext_buf ,
167+ .len = rsa_num_words ,
168+ };
169+
170+ bool status_resp = true;
171+ otcrypto_status_t status = otcrypto_rsa_encrypt (
172+ & public_key , hash_mode , input_message , label , ciphertext );
173+ if (status .value != kOtcryptoStatusValueOk ) {
174+ status_resp = false;
175+ }
176+
177+ // Return ciphertext and the status back to host.
178+ cryptotest_rsa_encrypt_resp_t uj_output ;
179+ memset (uj_output .ciphertext , 0 , RSA_CMD_MAX_MESSAGE_BYTES );
180+ memcpy (uj_output .ciphertext , ciphertext_buf , n_bytes );
181+ uj_output .ciphertext_len = n_bytes ;
182+ uj_output .result = status_resp ;
183+
184+ RESP_OK (ujson_serialize_cryptotest_rsa_encrypt_resp_t , uj , & uj_output );
185+ return OK_STATUS ();
186+ }
187+
54188status_t handle_rsa_decrypt (ujson_t * uj ) {
55189 cryptotest_rsa_decrypt_t uj_input ;
56190 TRY (ujson_deserialize_cryptotest_rsa_decrypt_t (uj , & uj_input ));
@@ -408,6 +542,8 @@ status_t handle_rsa(ujson_t *uj) {
408542 rsa_subcommand_t cmd ;
409543 TRY (ujson_deserialize_rsa_subcommand_t (uj , & cmd ));
410544 switch (cmd ) {
545+ case kRsaSubcommandRsaEncrypt :
546+ return handle_rsa_encrypt (uj );
411547 case kRsaSubcommandRsaDecrypt :
412548 return handle_rsa_decrypt (uj );
413549 case kRsaSubcommandRsaVerify :
0 commit comments