| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * QEMU Crypto cipher built-in algorithms | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2015 Red Hat, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							| 
									
										
										
										
											2019-02-13 16:54:59 +01:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 18:16:55 +00:00
										 |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | #include "crypto/aes.h"
 | 
					
						
							|  |  |  | #include "crypto/desrfb.h"
 | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  | #include "crypto/xts.h"
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:58 -04:00
										 |  |  | #include "cipherpriv.h"
 | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  | typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext; | 
					
						
							|  |  |  | struct QCryptoCipherBuiltinAESContext { | 
					
						
							|  |  |  |     AES_KEY enc; | 
					
						
							|  |  |  |     AES_KEY dec; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES; | 
					
						
							|  |  |  | struct QCryptoCipherBuiltinAES { | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |     QCryptoCipherBuiltinAESContext key; | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |     QCryptoCipherBuiltinAESContext key_tweak; | 
					
						
							| 
									
										
										
										
											2015-10-16 13:23:13 +01:00
										 |  |  |     uint8_t iv[AES_BLOCK_SIZE]; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB; | 
					
						
							|  |  |  | struct QCryptoCipherBuiltinDESRFB { | 
					
						
							|  |  |  |     uint8_t *key; | 
					
						
							|  |  |  |     size_t nkey; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin; | 
					
						
							|  |  |  | struct QCryptoCipherBuiltin { | 
					
						
							|  |  |  |     union { | 
					
						
							|  |  |  |         QCryptoCipherBuiltinAES aes; | 
					
						
							|  |  |  |         QCryptoCipherBuiltinDESRFB desrfb; | 
					
						
							|  |  |  |     } state; | 
					
						
							| 
									
										
										
										
											2015-10-16 16:35:06 +01:00
										 |  |  |     size_t blocksize; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     void (*free)(QCryptoCipher *cipher); | 
					
						
							|  |  |  |     int (*setiv)(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                  const uint8_t *iv, size_t niv, | 
					
						
							|  |  |  |                  Error **errp); | 
					
						
							|  |  |  |     int (*encrypt)(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                    const void *in, | 
					
						
							|  |  |  |                    void *out, | 
					
						
							|  |  |  |                    size_t len, | 
					
						
							|  |  |  |                    Error **errp); | 
					
						
							|  |  |  |     int (*decrypt)(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                    const void *in, | 
					
						
							|  |  |  |                    void *out, | 
					
						
							|  |  |  |                    size_t len, | 
					
						
							|  |  |  |                    Error **errp); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void qcrypto_cipher_free_aes(QCryptoCipher *cipher) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt = cipher->opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     g_free(ctxt); | 
					
						
							|  |  |  |     cipher->opaque = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 16:59:40 +08:00
										 |  |  | static void qcrypto_cipher_aes_ecb_encrypt(const AES_KEY *key, | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |                                            const void *in, | 
					
						
							|  |  |  |                                            void *out, | 
					
						
							|  |  |  |                                            size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const uint8_t *inptr = in; | 
					
						
							|  |  |  |     uint8_t *outptr = out; | 
					
						
							|  |  |  |     while (len) { | 
					
						
							|  |  |  |         if (len > AES_BLOCK_SIZE) { | 
					
						
							|  |  |  |             AES_encrypt(inptr, outptr, key); | 
					
						
							|  |  |  |             inptr += AES_BLOCK_SIZE; | 
					
						
							|  |  |  |             outptr += AES_BLOCK_SIZE; | 
					
						
							|  |  |  |             len -= AES_BLOCK_SIZE; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE]; | 
					
						
							|  |  |  |             memcpy(tmp1, inptr, len); | 
					
						
							|  |  |  |             /* Fill with 0 to avoid valgrind uninitialized reads */ | 
					
						
							|  |  |  |             memset(tmp1 + len, 0, sizeof(tmp1) - len); | 
					
						
							|  |  |  |             AES_encrypt(tmp1, tmp2, key); | 
					
						
							|  |  |  |             memcpy(outptr, tmp2, len); | 
					
						
							|  |  |  |             len = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 16:59:40 +08:00
										 |  |  | static void qcrypto_cipher_aes_ecb_decrypt(const AES_KEY *key, | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |                                            const void *in, | 
					
						
							|  |  |  |                                            void *out, | 
					
						
							|  |  |  |                                            size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const uint8_t *inptr = in; | 
					
						
							|  |  |  |     uint8_t *outptr = out; | 
					
						
							|  |  |  |     while (len) { | 
					
						
							|  |  |  |         if (len > AES_BLOCK_SIZE) { | 
					
						
							|  |  |  |             AES_decrypt(inptr, outptr, key); | 
					
						
							|  |  |  |             inptr += AES_BLOCK_SIZE; | 
					
						
							|  |  |  |             outptr += AES_BLOCK_SIZE; | 
					
						
							|  |  |  |             len -= AES_BLOCK_SIZE; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE]; | 
					
						
							|  |  |  |             memcpy(tmp1, inptr, len); | 
					
						
							|  |  |  |             /* Fill with 0 to avoid valgrind uninitialized reads */ | 
					
						
							|  |  |  |             memset(tmp1 + len, 0, sizeof(tmp1) - len); | 
					
						
							|  |  |  |             AES_decrypt(tmp1, tmp2, key); | 
					
						
							|  |  |  |             memcpy(outptr, tmp2, len); | 
					
						
							|  |  |  |             len = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  | static void qcrypto_cipher_aes_xts_encrypt(const void *ctx, | 
					
						
							|  |  |  |                                            size_t length, | 
					
						
							|  |  |  |                                            uint8_t *dst, | 
					
						
							|  |  |  |                                            const uint8_t *src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QCryptoCipherBuiltinAESContext *aesctx = ctx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 16:59:40 +08:00
										 |  |  |     qcrypto_cipher_aes_ecb_encrypt(&aesctx->enc, src, dst, length); | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void qcrypto_cipher_aes_xts_decrypt(const void *ctx, | 
					
						
							|  |  |  |                                            size_t length, | 
					
						
							|  |  |  |                                            uint8_t *dst, | 
					
						
							|  |  |  |                                            const uint8_t *src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QCryptoCipherBuiltinAESContext *aesctx = ctx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 16:59:40 +08:00
										 |  |  |     qcrypto_cipher_aes_ecb_decrypt(&aesctx->dec, src, dst, length); | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                                       const void *in, | 
					
						
							|  |  |  |                                       void *out, | 
					
						
							|  |  |  |                                       size_t len, | 
					
						
							|  |  |  |                                       Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt = cipher->opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |     switch (cipher->mode) { | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_MODE_ECB: | 
					
						
							|  |  |  |         qcrypto_cipher_aes_ecb_encrypt(&ctxt->state.aes.key.enc, | 
					
						
							|  |  |  |                                        in, out, len); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_MODE_CBC: | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |         AES_cbc_encrypt(in, out, len, | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |                         &ctxt->state.aes.key.enc, | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |                         ctxt->state.aes.iv, 1); | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |     case QCRYPTO_CIPHER_MODE_XTS: | 
					
						
							|  |  |  |         xts_encrypt(&ctxt->state.aes.key, | 
					
						
							|  |  |  |                     &ctxt->state.aes.key_tweak, | 
					
						
							|  |  |  |                     qcrypto_cipher_aes_xts_encrypt, | 
					
						
							|  |  |  |                     qcrypto_cipher_aes_xts_decrypt, | 
					
						
							|  |  |  |                     ctxt->state.aes.iv, | 
					
						
							|  |  |  |                     len, out, in); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |     default: | 
					
						
							|  |  |  |         g_assert_not_reached(); | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                                       const void *in, | 
					
						
							|  |  |  |                                       void *out, | 
					
						
							|  |  |  |                                       size_t len, | 
					
						
							|  |  |  |                                       Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt = cipher->opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |     switch (cipher->mode) { | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_MODE_ECB: | 
					
						
							|  |  |  |         qcrypto_cipher_aes_ecb_decrypt(&ctxt->state.aes.key.dec, | 
					
						
							|  |  |  |                                        in, out, len); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_MODE_CBC: | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |         AES_cbc_encrypt(in, out, len, | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |                         &ctxt->state.aes.key.dec, | 
					
						
							| 
									
										
										
										
											2015-07-24 13:23:54 +01:00
										 |  |  |                         ctxt->state.aes.iv, 0); | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |     case QCRYPTO_CIPHER_MODE_XTS: | 
					
						
							|  |  |  |         xts_decrypt(&ctxt->state.aes.key, | 
					
						
							|  |  |  |                     &ctxt->state.aes.key_tweak, | 
					
						
							|  |  |  |                     qcrypto_cipher_aes_xts_encrypt, | 
					
						
							|  |  |  |                     qcrypto_cipher_aes_xts_decrypt, | 
					
						
							|  |  |  |                     ctxt->state.aes.iv, | 
					
						
							|  |  |  |                     len, out, in); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |     default: | 
					
						
							|  |  |  |         g_assert_not_reached(); | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                                      const uint8_t *iv, size_t niv, | 
					
						
							|  |  |  |                                      Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt = cipher->opaque; | 
					
						
							| 
									
										
										
										
											2015-10-16 13:23:13 +01:00
										 |  |  |     if (niv != AES_BLOCK_SIZE) { | 
					
						
							|  |  |  |         error_setg(errp, "IV must be %d bytes not %zu", | 
					
						
							|  |  |  |                    AES_BLOCK_SIZE, niv); | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-16 13:23:13 +01:00
										 |  |  |     memcpy(ctxt->state.aes.iv, iv, AES_BLOCK_SIZE); | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  | static QCryptoCipherBuiltin * | 
					
						
							|  |  |  | qcrypto_cipher_init_aes(QCryptoCipherMode mode, | 
					
						
							|  |  |  |                         const uint8_t *key, size_t nkey, | 
					
						
							|  |  |  |                         Error **errp) | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |     if (mode != QCRYPTO_CIPHER_MODE_CBC && | 
					
						
							|  |  |  |         mode != QCRYPTO_CIPHER_MODE_ECB && | 
					
						
							|  |  |  |         mode != QCRYPTO_CIPHER_MODE_XTS) { | 
					
						
							| 
									
										
										
										
											2016-09-05 18:02:05 +01:00
										 |  |  |         error_setg(errp, "Unsupported cipher mode %s", | 
					
						
							| 
									
										
										
										
											2017-08-24 10:46:08 +02:00
										 |  |  |                    QCryptoCipherMode_str(mode)); | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ctxt = g_new0(QCryptoCipherBuiltin, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |     if (mode == QCRYPTO_CIPHER_MODE_XTS) { | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |         if (AES_set_encrypt_key(key, nkey * 4, &ctxt->state.aes.key.enc) != 0) { | 
					
						
							|  |  |  |             error_setg(errp, "Failed to set encryption key"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |         if (AES_set_decrypt_key(key, nkey * 4, &ctxt->state.aes.key.dec) != 0) { | 
					
						
							|  |  |  |             error_setg(errp, "Failed to set decryption key"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (AES_set_encrypt_key(key + (nkey / 2), nkey * 4, | 
					
						
							|  |  |  |                                 &ctxt->state.aes.key_tweak.enc) != 0) { | 
					
						
							|  |  |  |             error_setg(errp, "Failed to set encryption key"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (AES_set_decrypt_key(key + (nkey / 2), nkey * 4, | 
					
						
							|  |  |  |                                 &ctxt->state.aes.key_tweak.dec) != 0) { | 
					
						
							|  |  |  |             error_setg(errp, "Failed to set decryption key"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         if (AES_set_encrypt_key(key, nkey * 8, &ctxt->state.aes.key.enc) != 0) { | 
					
						
							|  |  |  |             error_setg(errp, "Failed to set encryption key"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (AES_set_decrypt_key(key, nkey * 8, &ctxt->state.aes.key.dec) != 0) { | 
					
						
							|  |  |  |             error_setg(errp, "Failed to set decryption key"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-16 16:35:06 +01:00
										 |  |  |     ctxt->blocksize = AES_BLOCK_SIZE; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     ctxt->free = qcrypto_cipher_free_aes; | 
					
						
							|  |  |  |     ctxt->setiv = qcrypto_cipher_setiv_aes; | 
					
						
							|  |  |  |     ctxt->encrypt = qcrypto_cipher_encrypt_aes; | 
					
						
							|  |  |  |     ctxt->decrypt = qcrypto_cipher_decrypt_aes; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |     return ctxt; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |  error: | 
					
						
							|  |  |  |     g_free(ctxt); | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void qcrypto_cipher_free_des_rfb(QCryptoCipher *cipher) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt = cipher->opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     g_free(ctxt->state.desrfb.key); | 
					
						
							|  |  |  |     g_free(ctxt); | 
					
						
							|  |  |  |     cipher->opaque = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                                           const void *in, | 
					
						
							|  |  |  |                                           void *out, | 
					
						
							|  |  |  |                                           size_t len, | 
					
						
							|  |  |  |                                           Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt = cipher->opaque; | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (len % 8) { | 
					
						
							|  |  |  |         error_setg(errp, "Buffer size must be multiple of 8 not %zu", | 
					
						
							|  |  |  |                    len); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     deskey(ctxt->state.desrfb.key, EN0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < len; i += 8) { | 
					
						
							|  |  |  |         des((void *)in + i, out + i); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                                           const void *in, | 
					
						
							|  |  |  |                                           void *out, | 
					
						
							|  |  |  |                                           size_t len, | 
					
						
							|  |  |  |                                           Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt = cipher->opaque; | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (len % 8) { | 
					
						
							|  |  |  |         error_setg(errp, "Buffer size must be multiple of 8 not %zu", | 
					
						
							|  |  |  |                    len); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     deskey(ctxt->state.desrfb.key, DE1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < len; i += 8) { | 
					
						
							|  |  |  |         des((void *)in + i, out + i); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                                         const uint8_t *iv, size_t niv, | 
					
						
							|  |  |  |                                         Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     error_setg(errp, "Setting IV is not supported"); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  | static QCryptoCipherBuiltin * | 
					
						
							|  |  |  | qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode, | 
					
						
							|  |  |  |                             const uint8_t *key, size_t nkey, | 
					
						
							|  |  |  |                             Error **errp) | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |     if (mode != QCRYPTO_CIPHER_MODE_ECB) { | 
					
						
							| 
									
										
										
										
											2016-09-05 18:02:05 +01:00
										 |  |  |         error_setg(errp, "Unsupported cipher mode %s", | 
					
						
							| 
									
										
										
										
											2017-08-24 10:46:08 +02:00
										 |  |  |                    QCryptoCipherMode_str(mode)); | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ctxt = g_new0(QCryptoCipherBuiltin, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ctxt->state.desrfb.key = g_new0(uint8_t, nkey); | 
					
						
							|  |  |  |     memcpy(ctxt->state.desrfb.key, key, nkey); | 
					
						
							|  |  |  |     ctxt->state.desrfb.nkey = nkey; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-16 16:35:06 +01:00
										 |  |  |     ctxt->blocksize = 8; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     ctxt->free = qcrypto_cipher_free_des_rfb; | 
					
						
							|  |  |  |     ctxt->setiv = qcrypto_cipher_setiv_des_rfb; | 
					
						
							|  |  |  |     ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb; | 
					
						
							|  |  |  |     ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |     return ctxt; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-26 17:23:21 +08:00
										 |  |  | bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, | 
					
						
							|  |  |  |                              QCryptoCipherMode mode) | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (alg) { | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_ALG_DES_RFB: | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_ALG_AES_128: | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_ALG_AES_192: | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_ALG_AES_256: | 
					
						
							| 
									
										
										
										
											2016-09-26 17:23:21 +08:00
										 |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (mode) { | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_MODE_ECB: | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_MODE_CBC: | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_MODE_XTS: | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2016-09-26 17:23:21 +08:00
										 |  |  |     case QCRYPTO_CIPHER_MODE_CTR: | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     default: | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  | static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, | 
					
						
							|  |  |  |                                                     QCryptoCipherMode mode, | 
					
						
							|  |  |  |                                                     const uint8_t *key, | 
					
						
							|  |  |  |                                                     size_t nkey, | 
					
						
							|  |  |  |                                                     Error **errp) | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |     QCryptoCipherBuiltin *ctxt; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-26 17:23:23 +08:00
										 |  |  |     switch (mode) { | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_MODE_ECB: | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_MODE_CBC: | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_MODE_XTS: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         error_setg(errp, "Unsupported cipher mode %s", | 
					
						
							| 
									
										
										
										
											2017-08-24 10:46:08 +02:00
										 |  |  |                    QCryptoCipherMode_str(mode)); | 
					
						
							| 
									
										
										
										
											2016-09-26 17:23:23 +08:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-11 14:05:21 +00:00
										 |  |  |     if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |     switch (alg) { | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     case QCRYPTO_CIPHER_ALG_DES_RFB: | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |         ctxt = qcrypto_cipher_init_des_rfb(mode, key, nkey, errp); | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_ALG_AES_128: | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_ALG_AES_192: | 
					
						
							|  |  |  |     case QCRYPTO_CIPHER_ALG_AES_256: | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |         ctxt = qcrypto_cipher_init_aes(mode, key, nkey, errp); | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         error_setg(errp, | 
					
						
							| 
									
										
										
										
											2016-09-05 18:02:05 +01:00
										 |  |  |                    "Unsupported cipher algorithm %s", | 
					
						
							| 
									
										
										
										
											2017-08-24 10:46:08 +02:00
										 |  |  |                    QCryptoCipherAlgorithm_str(alg)); | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  |     return ctxt; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:58 -04:00
										 |  |  | static void | 
					
						
							|  |  |  | qcrypto_builtin_cipher_ctx_free(QCryptoCipher *cipher) | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-07-09 16:52:48 +02:00
										 |  |  |     QCryptoCipherBuiltin *ctxt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ctxt = cipher->opaque; | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     ctxt->free(cipher); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:58 -04:00
										 |  |  | static int | 
					
						
							|  |  |  | qcrypto_builtin_cipher_encrypt(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                                const void *in, | 
					
						
							|  |  |  |                                void *out, | 
					
						
							|  |  |  |                                size_t len, | 
					
						
							|  |  |  |                                Error **errp) | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt = cipher->opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-16 16:35:06 +01:00
										 |  |  |     if (len % ctxt->blocksize) { | 
					
						
							|  |  |  |         error_setg(errp, "Length %zu must be a multiple of block size %zu", | 
					
						
							|  |  |  |                    len, ctxt->blocksize); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     return ctxt->encrypt(cipher, in, out, len, errp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:58 -04:00
										 |  |  | static int | 
					
						
							|  |  |  | qcrypto_builtin_cipher_decrypt(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                                const void *in, | 
					
						
							|  |  |  |                                void *out, | 
					
						
							|  |  |  |                                size_t len, | 
					
						
							|  |  |  |                                Error **errp) | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt = cipher->opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-16 16:35:06 +01:00
										 |  |  |     if (len % ctxt->blocksize) { | 
					
						
							|  |  |  |         error_setg(errp, "Length %zu must be a multiple of block size %zu", | 
					
						
							|  |  |  |                    len, ctxt->blocksize); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  |     return ctxt->decrypt(cipher, in, out, len, errp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:58 -04:00
										 |  |  | static int | 
					
						
							|  |  |  | qcrypto_builtin_cipher_setiv(QCryptoCipher *cipher, | 
					
						
							|  |  |  |                              const uint8_t *iv, size_t niv, | 
					
						
							|  |  |  |                              Error **errp) | 
					
						
							| 
									
										
										
										
											2015-07-01 18:10:32 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QCryptoCipherBuiltin *ctxt = cipher->opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ctxt->setiv(cipher, iv, niv, errp); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:57 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 14:03:58 -04:00
										 |  |  | static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { | 
					
						
							|  |  |  |     .cipher_encrypt = qcrypto_builtin_cipher_encrypt, | 
					
						
							|  |  |  |     .cipher_decrypt = qcrypto_builtin_cipher_decrypt, | 
					
						
							|  |  |  |     .cipher_setiv = qcrypto_builtin_cipher_setiv, | 
					
						
							|  |  |  |     .cipher_free = qcrypto_builtin_cipher_ctx_free, | 
					
						
							|  |  |  | }; |