1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
/*
* Hash algorithms, for libreswan
*
* Copyright (C) 2016-2019 Andrew Cagney <cagney@gnu.org>
* Copyright (C) 2019 D. Hugh Redelmeier <hugh@mimosa.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
*
* This program 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 General Public License
* for more details.
*/
#include <stdlib.h>
#include "lswalloc.h"
#include "lswlog.h"
#include "ike_alg.h"
#include "ike_alg_hash_ops.h"
#include "crypt_hash.h"
#include "crypt_symkey.h"
struct crypt_hash {
struct hash_context *context;
const char *name;
const struct hash_desc *desc;
struct logger *logger;
};
struct crypt_hash *crypt_hash_init(const char *name, const struct hash_desc *hash_desc,
struct logger *logger)
{
ldbgf(DBG_CRYPT, logger, "%s hash %s init",
name, hash_desc->common.fqn);
struct hash_context *context =
hash_desc->hash_ops->init(hash_desc, name);
if (context == NULL) {
return NULL;
}
struct crypt_hash hash = {
.context = context,
.name = name,
.desc = hash_desc,
.logger = logger,
};
return clone_thing(hash, name);
}
void crypt_hash_digest_symkey(struct crypt_hash *hash,
const char *name, PK11SymKey *symkey)
{
if (DBGP(DBG_CRYPT)) {
DBG_log("%s hash %s digest %s-key@%p (size %zu)",
hash->name, hash->desc->common.fqn,
name, symkey, sizeof_symkey(symkey));
LDBG_symkey(hash->logger, hash->name, name, symkey);
}
hash->desc->hash_ops->digest_symkey(hash->context, name, symkey);
}
void crypt_hash_digest_byte(struct crypt_hash *hash,
const char *name, uint8_t byte)
{
if (DBGP(DBG_CRYPT)) {
DBG_log("%s hash %s digest %s 0x%"PRIx8" (%"PRIu8")",
hash->name, hash->desc->common.fqn,
name, byte, byte);
DBG_dump_thing(NULL, byte);
}
hash->desc->hash_ops->digest_bytes(hash->context, name, &byte, 1);
}
void crypt_hash_digest_bytes(struct crypt_hash *hash,
const char *name,
const void *bytes,
size_t sizeof_bytes)
{
if (DBGP(DBG_CRYPT)) {
/*
* XXX: don't log BYTES using @POINTER syntax as it
* might be bogus - confusing refcnt.awk.
*/
DBG_log("%s hash %s digest %s (%p length %zu)",
hash->name, hash->desc->common.fqn,
name, bytes, sizeof_bytes);
DBG_dump(NULL, bytes, sizeof_bytes);
}
hash->desc->hash_ops->digest_bytes(hash->context, name, bytes, sizeof_bytes);
}
void crypt_hash_final_bytes(struct crypt_hash **hashp,
uint8_t *bytes, size_t sizeof_bytes)
{
struct crypt_hash *hash = *hashp;
/* Must be correct, else hash code can crash. */
passert(sizeof_bytes == hash->desc->hash_digest_size);
hash->desc->hash_ops->final_bytes(&hash->context, bytes, sizeof_bytes);
if (DBGP(DBG_CRYPT)) {
DBG_log("%s hash %s final bytes@%p (length %zu)",
hash->name, hash->desc->common.fqn,
bytes, sizeof_bytes);
DBG_dump(NULL, bytes, sizeof_bytes);
}
pfree(*hashp);
*hashp = hash = NULL;
}
struct crypt_mac crypt_hash_final_mac(struct crypt_hash **hashp)
{
struct crypt_hash *hash = *hashp;
struct crypt_mac output = { .len = hash->desc->hash_digest_size, };
passert(output.len <= sizeof(output.ptr/*array*/));
hash->desc->hash_ops->final_bytes(&hash->context, output.ptr, output.len);
if (DBGP(DBG_CRYPT)) {
DBG_log("%s hash %s final length %zu",
hash->name, hash->desc->common.fqn, output.len);
DBG_dump_hunk(NULL, output);
}
pfree(*hashp);
*hashp = hash = NULL;
return output;
}
PK11SymKey *crypt_hash_symkey(const char *name, const struct hash_desc *hash_desc,
const char *symkey_name, PK11SymKey *symkey,
struct logger *logger)
{
ldbgf(DBG_CRYPT, logger, "%s hash %s %s-key@%p (size %zu)",
name, hash_desc->common.fqn,
symkey_name, symkey, sizeof_symkey(symkey));
struct crypt_hash *hash = crypt_hash_init(name, hash_desc, logger);
crypt_hash_digest_symkey(hash, symkey_name, symkey);
struct crypt_mac out = crypt_hash_final_mac(&hash);
PK11SymKey *key = symkey_from_hunk(name, out, logger);
return key;
}
|