1 #include <stdlib.h> 2 #include <string.h> 3 #include <ctype.h> 4 #include <errno.h> 5 #include <gcrypt.h> 6 7 #include "libcryptsetup.h" 8 #include "internal.h" 9 10 #define MAX_DIGESTS 64 11 #define GCRYPT_REQ_VERSION "1.1.42" 12 13 int init_crypto(void) 14 { 15 if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) { 16 if (!gcry_check_version (GCRYPT_REQ_VERSION)) 17 return -ENOSYS; 18 19 /* FIXME: If gcrypt compiled to support POSIX 1003.1e capabilities, 20 * it drops all privileges during secure memory initialisation. 21 * For now, the only workaround is to disable secure memory in gcrypt. 22 * cryptsetup always need at least cap_sys_admin privilege for dm-ioctl 23 * and it locks its memory space anyway. 24 */ 25 #if 0 26 log_dbg("Initializing crypto backend (secure memory disabled)."); 27 gcry_control (GCRYCTL_DISABLE_SECMEM); 28 #else 29 log_dbg("Initializing crypto backend (using secure memory)."); 30 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); 31 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); 32 gcry_control (GCRYCTL_RESUME_SECMEM_WARN); 33 #endif 34 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); 35 } 36 37 return 0; 38 } 39 40 static int gcrypt_hash(void *data, int size, char *key, 41 int sizep, const char *passphrase) 42 { 43 gcry_md_hd_t md; 44 int algo = *((int *)data); 45 int len = gcry_md_get_algo_dlen(algo); 46 int round, i; 47 48 if (gcry_md_open(&md, algo, 0)) 49 return -1; 50 51 for(round = 0; size; round++) { 52 /* hack from hashalot to avoid null bytes in key */ 53 for(i = 0; i < round; i++) 54 gcry_md_write(md, "A", 1); 55 56 gcry_md_write(md, passphrase, sizep); 57 58 if (len > size) 59 len = size; 60 memcpy(key, gcry_md_read(md, algo), len); 61 62 key += len; 63 size -= len; 64 if (size) 65 gcry_md_reset(md); 66 } 67 68 gcry_md_close(md); 69 return 0; 70 } 71 72 static struct hash_type *gcrypt_get_hashes(void) 73 { 74 struct hash_type *hashes; 75 int size = MAX_DIGESTS; 76 int *list; 77 int i; 78 gcry_error_t r; 79 80 if (!gcry_check_version(GCRYPT_REQ_VERSION)) 81 return NULL; 82 83 list = (int *)malloc(sizeof(*list) * size); 84 if (!list) 85 return NULL; 86 87 r = gcry_md_list(list, &size); 88 if (r || !size) { 89 free(list); 90 return NULL; 91 } 92 93 hashes = malloc(sizeof(*hashes) * (size + 1)); 94 if (!hashes) { 95 free(list); 96 return NULL; 97 } 98 99 for(i = 0; i < size; i++) { 100 hashes[i].name = NULL; 101 hashes[i].private = NULL; 102 } 103 104 for(i = 0; i < size; i++) { 105 char *p; 106 107 hashes[i].name = strdup(gcry_md_algo_name(list[i])); 108 if(!hashes[i].name) 109 goto err; 110 for(p = (char *)hashes[i].name; *p; p++) 111 *p = tolower(*p); 112 hashes[i].private = malloc(sizeof(int)); 113 if(!hashes[i].private) 114 goto err; 115 *((int *)hashes[i].private) = list[i]; 116 hashes[i].fn = gcrypt_hash; 117 } 118 hashes[i].name = NULL; 119 hashes[i].private = NULL; 120 hashes[i].fn = NULL; 121 122 free(list); 123 124 return hashes; 125 126 err: 127 free(list); 128 for(i = 0; i < size; i++) { 129 free(hashes[i].name); 130 free(hashes[i].private); 131 } 132 free(hashes); 133 return NULL; 134 } 135 136 static void gcrypt_free_hashes(struct hash_type *hashes) 137 { 138 struct hash_type *hash; 139 140 for(hash = hashes; hash->name; hash++) { 141 free(hash->name); 142 free(hash->private); 143 } 144 145 free(hashes); 146 } 147 148 struct hash_backend hash_gcrypt_backend = { 149 .name = "libgcrypt", 150 .get_hashes = gcrypt_get_hashes, 151 .free_hashes = gcrypt_free_hashes 152 }; 153