Coverage Report

Created: 2025-11-11 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cryptsetup/lib/crypt_plain.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * cryptsetup plain device helper functions
4
 *
5
 * Copyright (C) 2004 Jana Saout <jana@saout.de>
6
 * Copyright (C) 2010-2025 Red Hat, Inc. All rights reserved.
7
 * Copyright (C) 2010-2025 Milan Broz
8
 */
9
10
#include <string.h>
11
#include <stdio.h>
12
#include <errno.h>
13
14
#include "libcryptsetup.h"
15
#include "internal.h"
16
17
static int hash(const char *hash_name, size_t key_size, char *key,
18
    size_t passphrase_size, const char *passphrase)
19
0
{
20
0
  struct crypt_hash *md = NULL;
21
0
  size_t len;
22
0
  int round, i, r = 0;
23
24
0
  if (crypt_hash_init(&md, hash_name))
25
0
    return -ENOENT;
26
27
0
  len = crypt_hash_size(hash_name);
28
29
0
  for(round = 0; key_size && !r; round++) {
30
    /* hack from hashalot to avoid null bytes in key */
31
0
    for(i = 0; i < round; i++)
32
0
      if (crypt_hash_write(md, "A", 1))
33
0
        r = 1;
34
35
0
    if (crypt_hash_write(md, passphrase, passphrase_size))
36
0
      r = 1;
37
38
0
    if (len > key_size)
39
0
      len = key_size;
40
41
0
    if (crypt_hash_final(md, key, len))
42
0
      r = 1;
43
44
0
    key += len;
45
0
    key_size -= len;
46
0
  }
47
48
0
  crypt_hash_destroy(md);
49
0
  return r;
50
0
}
51
52
0
#define PLAIN_HASH_LEN_MAX 256
53
54
int crypt_plain_hash(struct crypt_device *cd,
55
         const char *hash_name,
56
         char *key, size_t key_size,
57
         const char *passphrase, size_t passphrase_size)
58
0
{
59
0
  char hash_name_buf[PLAIN_HASH_LEN_MAX], *s;
60
0
  size_t hash_size, pad_size;
61
0
  int r;
62
63
0
  log_dbg(cd, "Plain: hashing passphrase using %s.", hash_name);
64
65
0
  if (strlen(hash_name) >= PLAIN_HASH_LEN_MAX)
66
0
    return -EINVAL;
67
0
  strncpy(hash_name_buf, hash_name, PLAIN_HASH_LEN_MAX);
68
0
  hash_name_buf[PLAIN_HASH_LEN_MAX - 1] = '\0';
69
70
  /* hash[:hash_length] */
71
0
  if ((s = strchr(hash_name_buf, ':'))) {
72
0
    *s = '\0';
73
0
    s++;
74
0
    if (!*s || sscanf(s, "%zd", &hash_size) != 1) {
75
0
      log_dbg(cd, "Hash length is not a number");
76
0
      return -EINVAL;
77
0
    }
78
0
    if (hash_size > key_size) {
79
0
      log_dbg(cd, "Hash length %zd > key length %zd",
80
0
        hash_size, key_size);
81
0
      return -EINVAL;
82
0
    }
83
0
    pad_size = key_size - hash_size;
84
0
  } else {
85
0
    hash_size = key_size;
86
0
    pad_size = 0;
87
0
  }
88
89
  /* No hash, copy passphrase directly */
90
0
  if (!strcmp(hash_name_buf, "plain")) {
91
0
    if (passphrase_size < hash_size) {
92
0
      log_dbg(cd, "Too short plain passphrase.");
93
0
      return -EINVAL;
94
0
    }
95
0
    crypt_safe_memcpy(key, passphrase, hash_size);
96
0
    r = 0;
97
0
  } else
98
0
    r = hash(hash_name_buf, hash_size, key, passphrase_size, passphrase);
99
100
0
  if (r == 0 && pad_size)
101
0
    memset(key + hash_size, 0, pad_size);
102
103
0
  return r;
104
0
}