1717#include <linux/set_memory.h>
1818#include <linux/fs.h>
1919#include <linux/tsm.h>
20- #include <crypto/aead.h>
21- #include <linux/scatterlist.h>
20+ #include <crypto/gcm.h>
2221#include <linux/psp-sev.h>
2322#include <linux/sockptr.h>
2423#include <linux/cleanup.h>
3130#include <asm/sev.h>
3231
3332#define DEVICE_NAME "sev-guest"
34- #define AAD_LEN 48
35- #define MSG_HDR_VER 1
3633
3734#define SNP_REQ_MAX_RETRY_DURATION (60*HZ)
3835#define SNP_REQ_RETRY_DELAY (2*HZ)
3936
4037#define SVSM_MAX_RETRIES 3
4138
42- struct snp_guest_crypto {
43- struct crypto_aead * tfm ;
44- u8 * iv , * authtag ;
45- int iv_len , a_len ;
46- };
47-
4839struct snp_guest_dev {
4940 struct device * dev ;
5041 struct miscdevice misc ;
5142
5243 void * certs_data ;
53- struct snp_guest_crypto * crypto ;
44+ struct aesgcm_ctx * ctx ;
5445 /* request and response are in unencrypted memory */
5546 struct snp_guest_msg * request , * response ;
5647
@@ -169,132 +160,31 @@ static inline struct snp_guest_dev *to_snp_dev(struct file *file)
169160 return container_of (dev , struct snp_guest_dev , misc );
170161}
171162
172- static struct snp_guest_crypto * init_crypto ( struct snp_guest_dev * snp_dev , u8 * key , size_t keylen )
163+ static struct aesgcm_ctx * snp_init_crypto ( u8 * key , size_t keylen )
173164{
174- struct snp_guest_crypto * crypto ;
165+ struct aesgcm_ctx * ctx ;
175166
176- crypto = kzalloc (sizeof (* crypto ), GFP_KERNEL_ACCOUNT );
177- if (!crypto )
167+ ctx = kzalloc (sizeof (* ctx ), GFP_KERNEL_ACCOUNT );
168+ if (!ctx )
178169 return NULL ;
179170
180- crypto -> tfm = crypto_alloc_aead ("gcm(aes)" , 0 , 0 );
181- if (IS_ERR (crypto -> tfm ))
182- goto e_free ;
183-
184- if (crypto_aead_setkey (crypto -> tfm , key , keylen ))
185- goto e_free_crypto ;
186-
187- crypto -> iv_len = crypto_aead_ivsize (crypto -> tfm );
188- crypto -> iv = kmalloc (crypto -> iv_len , GFP_KERNEL_ACCOUNT );
189- if (!crypto -> iv )
190- goto e_free_crypto ;
191-
192- if (crypto_aead_authsize (crypto -> tfm ) > MAX_AUTHTAG_LEN ) {
193- if (crypto_aead_setauthsize (crypto -> tfm , MAX_AUTHTAG_LEN )) {
194- dev_err (snp_dev -> dev , "failed to set authsize to %d\n" , MAX_AUTHTAG_LEN );
195- goto e_free_iv ;
196- }
171+ if (aesgcm_expandkey (ctx , key , keylen , AUTHTAG_LEN )) {
172+ pr_err ("Crypto context initialization failed\n" );
173+ kfree (ctx );
174+ return NULL ;
197175 }
198176
199- crypto -> a_len = crypto_aead_authsize (crypto -> tfm );
200- crypto -> authtag = kmalloc (crypto -> a_len , GFP_KERNEL_ACCOUNT );
201- if (!crypto -> authtag )
202- goto e_free_iv ;
203-
204- return crypto ;
205-
206- e_free_iv :
207- kfree (crypto -> iv );
208- e_free_crypto :
209- crypto_free_aead (crypto -> tfm );
210- e_free :
211- kfree (crypto );
212-
213- return NULL ;
214- }
215-
216- static void deinit_crypto (struct snp_guest_crypto * crypto )
217- {
218- crypto_free_aead (crypto -> tfm );
219- kfree (crypto -> iv );
220- kfree (crypto -> authtag );
221- kfree (crypto );
222- }
223-
224- static int enc_dec_message (struct snp_guest_crypto * crypto , struct snp_guest_msg * msg ,
225- u8 * src_buf , u8 * dst_buf , size_t len , bool enc )
226- {
227- struct snp_guest_msg_hdr * hdr = & msg -> hdr ;
228- struct scatterlist src [3 ], dst [3 ];
229- DECLARE_CRYPTO_WAIT (wait );
230- struct aead_request * req ;
231- int ret ;
232-
233- req = aead_request_alloc (crypto -> tfm , GFP_KERNEL );
234- if (!req )
235- return - ENOMEM ;
236-
237- /*
238- * AEAD memory operations:
239- * +------ AAD -------+------- DATA -----+---- AUTHTAG----+
240- * | msg header | plaintext | hdr->authtag |
241- * | bytes 30h - 5Fh | or | |
242- * | | cipher | |
243- * +------------------+------------------+----------------+
244- */
245- sg_init_table (src , 3 );
246- sg_set_buf (& src [0 ], & hdr -> algo , AAD_LEN );
247- sg_set_buf (& src [1 ], src_buf , hdr -> msg_sz );
248- sg_set_buf (& src [2 ], hdr -> authtag , crypto -> a_len );
249-
250- sg_init_table (dst , 3 );
251- sg_set_buf (& dst [0 ], & hdr -> algo , AAD_LEN );
252- sg_set_buf (& dst [1 ], dst_buf , hdr -> msg_sz );
253- sg_set_buf (& dst [2 ], hdr -> authtag , crypto -> a_len );
254-
255- aead_request_set_ad (req , AAD_LEN );
256- aead_request_set_tfm (req , crypto -> tfm );
257- aead_request_set_callback (req , 0 , crypto_req_done , & wait );
258-
259- aead_request_set_crypt (req , src , dst , len , crypto -> iv );
260- ret = crypto_wait_req (enc ? crypto_aead_encrypt (req ) : crypto_aead_decrypt (req ), & wait );
261-
262- aead_request_free (req );
263- return ret ;
264- }
265-
266- static int __enc_payload (struct snp_guest_dev * snp_dev , struct snp_guest_msg * msg ,
267- void * plaintext , size_t len )
268- {
269- struct snp_guest_crypto * crypto = snp_dev -> crypto ;
270- struct snp_guest_msg_hdr * hdr = & msg -> hdr ;
271-
272- memset (crypto -> iv , 0 , crypto -> iv_len );
273- memcpy (crypto -> iv , & hdr -> msg_seqno , sizeof (hdr -> msg_seqno ));
274-
275- return enc_dec_message (crypto , msg , plaintext , msg -> payload , len , true);
276- }
277-
278- static int dec_payload (struct snp_guest_dev * snp_dev , struct snp_guest_msg * msg ,
279- void * plaintext , size_t len )
280- {
281- struct snp_guest_crypto * crypto = snp_dev -> crypto ;
282- struct snp_guest_msg_hdr * hdr = & msg -> hdr ;
283-
284- /* Build IV with response buffer sequence number */
285- memset (crypto -> iv , 0 , crypto -> iv_len );
286- memcpy (crypto -> iv , & hdr -> msg_seqno , sizeof (hdr -> msg_seqno ));
287-
288- return enc_dec_message (crypto , msg , msg -> payload , plaintext , len , false);
177+ return ctx ;
289178}
290179
291180static int verify_and_dec_payload (struct snp_guest_dev * snp_dev , void * payload , u32 sz )
292181{
293- struct snp_guest_crypto * crypto = snp_dev -> crypto ;
294182 struct snp_guest_msg * resp_msg = & snp_dev -> secret_response ;
295183 struct snp_guest_msg * req_msg = & snp_dev -> secret_request ;
296184 struct snp_guest_msg_hdr * req_msg_hdr = & req_msg -> hdr ;
297185 struct snp_guest_msg_hdr * resp_msg_hdr = & resp_msg -> hdr ;
186+ struct aesgcm_ctx * ctx = snp_dev -> ctx ;
187+ u8 iv [GCM_AES_IV_SIZE ] = {};
298188
299189 pr_debug ("response [seqno %lld type %d version %d sz %d]\n" ,
300190 resp_msg_hdr -> msg_seqno , resp_msg_hdr -> msg_type , resp_msg_hdr -> msg_version ,
@@ -316,18 +206,25 @@ static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload,
316206 * If the message size is greater than our buffer length then return
317207 * an error.
318208 */
319- if (unlikely ((resp_msg_hdr -> msg_sz + crypto -> a_len ) > sz ))
209+ if (unlikely ((resp_msg_hdr -> msg_sz + ctx -> authsize ) > sz ))
320210 return - EBADMSG ;
321211
322212 /* Decrypt the payload */
323- return dec_payload (snp_dev , resp_msg , payload , resp_msg_hdr -> msg_sz + crypto -> a_len );
213+ memcpy (iv , & resp_msg_hdr -> msg_seqno , min (sizeof (iv ), sizeof (resp_msg_hdr -> msg_seqno )));
214+ if (!aesgcm_decrypt (ctx , payload , resp_msg -> payload , resp_msg_hdr -> msg_sz ,
215+ & resp_msg_hdr -> algo , AAD_LEN , iv , resp_msg_hdr -> authtag ))
216+ return - EBADMSG ;
217+
218+ return 0 ;
324219}
325220
326221static int enc_payload (struct snp_guest_dev * snp_dev , u64 seqno , int version , u8 type ,
327222 void * payload , size_t sz )
328223{
329224 struct snp_guest_msg * msg = & snp_dev -> secret_request ;
330225 struct snp_guest_msg_hdr * hdr = & msg -> hdr ;
226+ struct aesgcm_ctx * ctx = snp_dev -> ctx ;
227+ u8 iv [GCM_AES_IV_SIZE ] = {};
331228
332229 memset (msg , 0 , sizeof (* msg ));
333230
@@ -347,7 +244,14 @@ static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8
347244 pr_debug ("request [seqno %lld type %d version %d sz %d]\n" ,
348245 hdr -> msg_seqno , hdr -> msg_type , hdr -> msg_version , hdr -> msg_sz );
349246
350- return __enc_payload (snp_dev , msg , payload , sz );
247+ if (WARN_ON ((sz + ctx -> authsize ) > sizeof (msg -> payload )))
248+ return - EBADMSG ;
249+
250+ memcpy (iv , & hdr -> msg_seqno , min (sizeof (iv ), sizeof (hdr -> msg_seqno )));
251+ aesgcm_encrypt (ctx , msg -> payload , payload , sz , & hdr -> algo , AAD_LEN ,
252+ iv , hdr -> authtag );
253+
254+ return 0 ;
351255}
352256
353257static int __handle_guest_request (struct snp_guest_dev * snp_dev , u64 exit_code ,
@@ -495,7 +399,6 @@ struct snp_req_resp {
495399
496400static int get_report (struct snp_guest_dev * snp_dev , struct snp_guest_request_ioctl * arg )
497401{
498- struct snp_guest_crypto * crypto = snp_dev -> crypto ;
499402 struct snp_report_req * report_req = & snp_dev -> req .report ;
500403 struct snp_report_resp * report_resp ;
501404 int rc , resp_len ;
@@ -513,7 +416,7 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io
513416 * response payload. Make sure that it has enough space to cover the
514417 * authtag.
515418 */
516- resp_len = sizeof (report_resp -> data ) + crypto -> a_len ;
419+ resp_len = sizeof (report_resp -> data ) + snp_dev -> ctx -> authsize ;
517420 report_resp = kzalloc (resp_len , GFP_KERNEL_ACCOUNT );
518421 if (!report_resp )
519422 return - ENOMEM ;
@@ -534,7 +437,6 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io
534437static int get_derived_key (struct snp_guest_dev * snp_dev , struct snp_guest_request_ioctl * arg )
535438{
536439 struct snp_derived_key_req * derived_key_req = & snp_dev -> req .derived_key ;
537- struct snp_guest_crypto * crypto = snp_dev -> crypto ;
538440 struct snp_derived_key_resp derived_key_resp = {0 };
539441 int rc , resp_len ;
540442 /* Response data is 64 bytes and max authsize for GCM is 16 bytes. */
@@ -550,7 +452,7 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque
550452 * response payload. Make sure that it has enough space to cover the
551453 * authtag.
552454 */
553- resp_len = sizeof (derived_key_resp .data ) + crypto -> a_len ;
455+ resp_len = sizeof (derived_key_resp .data ) + snp_dev -> ctx -> authsize ;
554456 if (sizeof (buf ) < resp_len )
555457 return - ENOMEM ;
556458
@@ -579,7 +481,6 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
579481
580482{
581483 struct snp_ext_report_req * report_req = & snp_dev -> req .ext_report ;
582- struct snp_guest_crypto * crypto = snp_dev -> crypto ;
583484 struct snp_report_resp * report_resp ;
584485 int ret , npages = 0 , resp_len ;
585486 sockptr_t certs_address ;
@@ -622,7 +523,7 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
622523 * response payload. Make sure that it has enough space to cover the
623524 * authtag.
624525 */
625- resp_len = sizeof (report_resp -> data ) + crypto -> a_len ;
526+ resp_len = sizeof (report_resp -> data ) + snp_dev -> ctx -> authsize ;
626527 report_resp = kzalloc (resp_len , GFP_KERNEL_ACCOUNT );
627528 if (!report_resp )
628529 return - ENOMEM ;
@@ -1147,8 +1048,8 @@ static int __init sev_guest_probe(struct platform_device *pdev)
11471048 goto e_free_response ;
11481049
11491050 ret = - EIO ;
1150- snp_dev -> crypto = init_crypto ( snp_dev , snp_dev -> vmpck , VMPCK_KEY_LEN );
1151- if (!snp_dev -> crypto )
1051+ snp_dev -> ctx = snp_init_crypto ( snp_dev -> vmpck , VMPCK_KEY_LEN );
1052+ if (!snp_dev -> ctx )
11521053 goto e_free_cert_data ;
11531054
11541055 misc = & snp_dev -> misc ;
@@ -1174,11 +1075,13 @@ static int __init sev_guest_probe(struct platform_device *pdev)
11741075
11751076 ret = misc_register (misc );
11761077 if (ret )
1177- goto e_free_cert_data ;
1078+ goto e_free_ctx ;
11781079
11791080 dev_info (dev , "Initialized SEV guest driver (using VMPCK%d communication key)\n" , vmpck_id );
11801081 return 0 ;
11811082
1083+ e_free_ctx :
1084+ kfree (snp_dev -> ctx );
11821085e_free_cert_data :
11831086 free_shared_pages (snp_dev -> certs_data , SEV_FW_BLOB_MAX_SIZE );
11841087e_free_response :
@@ -1197,7 +1100,7 @@ static void __exit sev_guest_remove(struct platform_device *pdev)
11971100 free_shared_pages (snp_dev -> certs_data , SEV_FW_BLOB_MAX_SIZE );
11981101 free_shared_pages (snp_dev -> response , sizeof (struct snp_guest_msg ));
11991102 free_shared_pages (snp_dev -> request , sizeof (struct snp_guest_msg ));
1200- deinit_crypto (snp_dev -> crypto );
1103+ kfree (snp_dev -> ctx );
12011104 misc_deregister (& snp_dev -> misc );
12021105}
12031106
0 commit comments