Switch to new crypto backend interface.
[platform/upstream/cryptsetup.git] / lib / crypt_plain.c
1 /*
2  * cryptsetup plain device helper functions
3  *
4  * Copyright (C) 2004 Christophe Saout <christophe@saout.de>
5  * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <string.h>
22 #include <stdlib.h>
23 #include <errno.h>
24
25 #include "internal.h"
26 #include "crypto_backend.h"
27
28 static int hash(const char *hash_name, int size, char *key,
29                 int sizep, const char *passphrase)
30 {
31         struct crypt_hash *md = NULL;
32         size_t slen;
33         int len = crypt_hash_size(hash_name);
34         int round, i;
35
36         if (crypt_hash_init(&md, hash_name))
37                 return -ENOENT;
38
39         for(round = 0; size; round++) {
40                 /* hack from hashalot to avoid null bytes in key */
41                 for(i = 0; i < round; i++)
42                         crypt_hash_write(md, "A", 1);
43
44                 crypt_hash_write(md, passphrase, sizep);
45
46                 if (len > size)
47                         len = size;
48                 slen = len;
49                 crypt_hash_final(md, key, slen);
50                 // FIXME: if slen != len
51
52                 key += len;
53                 size -= len;
54                 if (size)
55                         crypt_hash_restart(md);
56         }
57
58         crypt_hash_destroy(md);
59         return 0;
60 }
61
62 int crypt_plain_hash(struct crypt_device *ctx, const char *hash_name,
63                      char *result, size_t size,
64                      const char *passphrase, size_t sizep)
65 {
66         char hash_name_buf[256], *s;
67         size_t hlen, pad = 0;
68         int r;
69
70         if (strlen(hash_name) >= sizeof(hash_name_buf))
71                 return -EINVAL;
72
73         if ((s = strchr(hash_name, ':'))) {
74                 strcpy(hash_name_buf, hash_name);
75                 hash_name_buf[s-hash_name] = '\0';
76                 hash_name = hash_name_buf;
77                 hlen = atoi(++s);
78                 if (hlen > size) {
79                         log_err(ctx, "Requested hash length (%zd) > key length (%zd)\n", hlen, size);
80                         return -EINVAL;
81                 }
82                 pad = size-hlen;
83                 size = hlen;
84         }
85
86         r = hash(hash_name, size, result, sizep, passphrase);
87         if (r < 0)
88                 log_err(ctx, "Hash algorithm %s not supported.\n", hash_name);
89
90         if (r == 0 && pad)
91                 memset(result+size, 0, pad);
92
93         return r;
94 }