xref: /aosp_15_r20/external/fsverity-utils/lib/hash_algs.c (revision b13c0e4024008a1f948ee8189745cb3371f4ac04)
1*b13c0e40SEric Biggers // SPDX-License-Identifier: MIT
2*b13c0e40SEric Biggers /*
3*b13c0e40SEric Biggers  * fs-verity hash algorithms
4*b13c0e40SEric Biggers  *
5*b13c0e40SEric Biggers  * Copyright 2018 Google LLC
6*b13c0e40SEric Biggers  *
7*b13c0e40SEric Biggers  * Use of this source code is governed by an MIT-style
8*b13c0e40SEric Biggers  * license that can be found in the LICENSE file or at
9*b13c0e40SEric Biggers  * https://opensource.org/licenses/MIT.
10*b13c0e40SEric Biggers  */
11*b13c0e40SEric Biggers 
12*b13c0e40SEric Biggers #include "lib_private.h"
13*b13c0e40SEric Biggers 
14*b13c0e40SEric Biggers #include <openssl/evp.h>
15*b13c0e40SEric Biggers #include <stdlib.h>
16*b13c0e40SEric Biggers #include <string.h>
17*b13c0e40SEric Biggers 
18*b13c0e40SEric Biggers /* ========== libcrypto (OpenSSL) wrappers ========== */
19*b13c0e40SEric Biggers 
20*b13c0e40SEric Biggers struct openssl_hash_ctx {
21*b13c0e40SEric Biggers 	struct hash_ctx base;	/* must be first */
22*b13c0e40SEric Biggers 	EVP_MD_CTX *md_ctx;
23*b13c0e40SEric Biggers 	const EVP_MD *md;
24*b13c0e40SEric Biggers };
25*b13c0e40SEric Biggers 
openssl_digest_init(struct hash_ctx * _ctx)26*b13c0e40SEric Biggers static void openssl_digest_init(struct hash_ctx *_ctx)
27*b13c0e40SEric Biggers {
28*b13c0e40SEric Biggers 	struct openssl_hash_ctx *ctx = (void *)_ctx;
29*b13c0e40SEric Biggers 	int ret;
30*b13c0e40SEric Biggers 
31*b13c0e40SEric Biggers 	ret = EVP_DigestInit_ex(ctx->md_ctx, ctx->md, NULL);
32*b13c0e40SEric Biggers 	BUG_ON(ret != 1);
33*b13c0e40SEric Biggers }
34*b13c0e40SEric Biggers 
openssl_digest_update(struct hash_ctx * _ctx,const void * data,size_t size)35*b13c0e40SEric Biggers static void openssl_digest_update(struct hash_ctx *_ctx,
36*b13c0e40SEric Biggers 				  const void *data, size_t size)
37*b13c0e40SEric Biggers {
38*b13c0e40SEric Biggers 	struct openssl_hash_ctx *ctx = (void *)_ctx;
39*b13c0e40SEric Biggers 	int ret;
40*b13c0e40SEric Biggers 
41*b13c0e40SEric Biggers 	ret = EVP_DigestUpdate(ctx->md_ctx, data, size);
42*b13c0e40SEric Biggers 	BUG_ON(ret != 1);
43*b13c0e40SEric Biggers }
44*b13c0e40SEric Biggers 
openssl_digest_final(struct hash_ctx * _ctx,u8 * digest)45*b13c0e40SEric Biggers static void openssl_digest_final(struct hash_ctx *_ctx, u8 *digest)
46*b13c0e40SEric Biggers {
47*b13c0e40SEric Biggers 	struct openssl_hash_ctx *ctx = (void *)_ctx;
48*b13c0e40SEric Biggers 	int ret;
49*b13c0e40SEric Biggers 
50*b13c0e40SEric Biggers 	ret = EVP_DigestFinal_ex(ctx->md_ctx, digest, NULL);
51*b13c0e40SEric Biggers 	BUG_ON(ret != 1);
52*b13c0e40SEric Biggers }
53*b13c0e40SEric Biggers 
openssl_digest_ctx_free(struct hash_ctx * _ctx)54*b13c0e40SEric Biggers static void openssl_digest_ctx_free(struct hash_ctx *_ctx)
55*b13c0e40SEric Biggers {
56*b13c0e40SEric Biggers 	struct openssl_hash_ctx *ctx = (void *)_ctx;
57*b13c0e40SEric Biggers 
58*b13c0e40SEric Biggers 	/*
59*b13c0e40SEric Biggers 	 * OpenSSL 1.1.0 renamed EVP_MD_CTX_destroy() to EVP_MD_CTX_free() but
60*b13c0e40SEric Biggers 	 * kept the old name as a macro.  Use the old name for compatibility
61*b13c0e40SEric Biggers 	 * with older OpenSSL versions.
62*b13c0e40SEric Biggers 	 */
63*b13c0e40SEric Biggers 	EVP_MD_CTX_destroy(ctx->md_ctx);
64*b13c0e40SEric Biggers 	free(ctx);
65*b13c0e40SEric Biggers }
66*b13c0e40SEric Biggers 
67*b13c0e40SEric Biggers static struct hash_ctx *
openssl_digest_ctx_create(const struct fsverity_hash_alg * alg,const EVP_MD * md)68*b13c0e40SEric Biggers openssl_digest_ctx_create(const struct fsverity_hash_alg *alg, const EVP_MD *md)
69*b13c0e40SEric Biggers {
70*b13c0e40SEric Biggers 	struct openssl_hash_ctx *ctx;
71*b13c0e40SEric Biggers 
72*b13c0e40SEric Biggers 	ctx = libfsverity_zalloc(sizeof(*ctx));
73*b13c0e40SEric Biggers 	if (!ctx)
74*b13c0e40SEric Biggers 		return NULL;
75*b13c0e40SEric Biggers 
76*b13c0e40SEric Biggers 	ctx->base.alg = alg;
77*b13c0e40SEric Biggers 	ctx->base.init = openssl_digest_init;
78*b13c0e40SEric Biggers 	ctx->base.update = openssl_digest_update;
79*b13c0e40SEric Biggers 	ctx->base.final = openssl_digest_final;
80*b13c0e40SEric Biggers 	ctx->base.free = openssl_digest_ctx_free;
81*b13c0e40SEric Biggers 	/*
82*b13c0e40SEric Biggers 	 * OpenSSL 1.1.0 renamed EVP_MD_CTX_create() to EVP_MD_CTX_new() but
83*b13c0e40SEric Biggers 	 * kept the old name as a macro.  Use the old name for compatibility
84*b13c0e40SEric Biggers 	 * with older OpenSSL versions.
85*b13c0e40SEric Biggers 	 */
86*b13c0e40SEric Biggers 	ctx->md_ctx = EVP_MD_CTX_create();
87*b13c0e40SEric Biggers 	if (!ctx->md_ctx) {
88*b13c0e40SEric Biggers 		libfsverity_error_msg("failed to allocate EVP_MD_CTX");
89*b13c0e40SEric Biggers 		goto err1;
90*b13c0e40SEric Biggers 	}
91*b13c0e40SEric Biggers 
92*b13c0e40SEric Biggers 	ctx->md = md;
93*b13c0e40SEric Biggers 	if (WARN_ON(EVP_MD_size(md) != alg->digest_size))
94*b13c0e40SEric Biggers 		goto err2;
95*b13c0e40SEric Biggers 
96*b13c0e40SEric Biggers 	return &ctx->base;
97*b13c0e40SEric Biggers 
98*b13c0e40SEric Biggers err2:
99*b13c0e40SEric Biggers 	EVP_MD_CTX_destroy(ctx->md_ctx);
100*b13c0e40SEric Biggers err1:
101*b13c0e40SEric Biggers 	free(ctx);
102*b13c0e40SEric Biggers 	return NULL;
103*b13c0e40SEric Biggers }
104*b13c0e40SEric Biggers 
create_sha256_ctx(const struct fsverity_hash_alg * alg)105*b13c0e40SEric Biggers static struct hash_ctx *create_sha256_ctx(const struct fsverity_hash_alg *alg)
106*b13c0e40SEric Biggers {
107*b13c0e40SEric Biggers 	return openssl_digest_ctx_create(alg, EVP_sha256());
108*b13c0e40SEric Biggers }
109*b13c0e40SEric Biggers 
create_sha512_ctx(const struct fsverity_hash_alg * alg)110*b13c0e40SEric Biggers static struct hash_ctx *create_sha512_ctx(const struct fsverity_hash_alg *alg)
111*b13c0e40SEric Biggers {
112*b13c0e40SEric Biggers 	return openssl_digest_ctx_create(alg, EVP_sha512());
113*b13c0e40SEric Biggers }
114*b13c0e40SEric Biggers 
115*b13c0e40SEric Biggers /* ========== Hash utilities ========== */
116*b13c0e40SEric Biggers 
libfsverity_hash_init(struct hash_ctx * ctx)117*b13c0e40SEric Biggers void libfsverity_hash_init(struct hash_ctx *ctx)
118*b13c0e40SEric Biggers {
119*b13c0e40SEric Biggers 	ctx->init(ctx);
120*b13c0e40SEric Biggers }
121*b13c0e40SEric Biggers 
libfsverity_hash_update(struct hash_ctx * ctx,const void * data,size_t size)122*b13c0e40SEric Biggers void libfsverity_hash_update(struct hash_ctx *ctx, const void *data,
123*b13c0e40SEric Biggers 			     size_t size)
124*b13c0e40SEric Biggers {
125*b13c0e40SEric Biggers 	ctx->update(ctx, data, size);
126*b13c0e40SEric Biggers }
127*b13c0e40SEric Biggers 
libfsverity_hash_final(struct hash_ctx * ctx,u8 * digest)128*b13c0e40SEric Biggers void libfsverity_hash_final(struct hash_ctx *ctx, u8 *digest)
129*b13c0e40SEric Biggers {
130*b13c0e40SEric Biggers 	ctx->final(ctx, digest);
131*b13c0e40SEric Biggers }
132*b13c0e40SEric Biggers 
133*b13c0e40SEric Biggers /* ->init(), ->update(), and ->final() all in one step */
libfsverity_hash_full(struct hash_ctx * ctx,const void * data,size_t size,u8 * digest)134*b13c0e40SEric Biggers void libfsverity_hash_full(struct hash_ctx *ctx, const void *data, size_t size,
135*b13c0e40SEric Biggers 			   u8 *digest)
136*b13c0e40SEric Biggers {
137*b13c0e40SEric Biggers 	libfsverity_hash_init(ctx);
138*b13c0e40SEric Biggers 	libfsverity_hash_update(ctx, data, size);
139*b13c0e40SEric Biggers 	libfsverity_hash_final(ctx, digest);
140*b13c0e40SEric Biggers }
141*b13c0e40SEric Biggers 
libfsverity_free_hash_ctx(struct hash_ctx * ctx)142*b13c0e40SEric Biggers void libfsverity_free_hash_ctx(struct hash_ctx *ctx)
143*b13c0e40SEric Biggers {
144*b13c0e40SEric Biggers 	if (ctx)
145*b13c0e40SEric Biggers 		ctx->free(ctx);
146*b13c0e40SEric Biggers }
147*b13c0e40SEric Biggers 
148*b13c0e40SEric Biggers /* ========== Hash algorithm definitions ========== */
149*b13c0e40SEric Biggers 
150*b13c0e40SEric Biggers static const struct fsverity_hash_alg fsverity_hash_algs[] = {
151*b13c0e40SEric Biggers 	[FS_VERITY_HASH_ALG_SHA256] = {
152*b13c0e40SEric Biggers 		.name = "sha256",
153*b13c0e40SEric Biggers 		.digest_size = 32,
154*b13c0e40SEric Biggers 		.block_size = 64,
155*b13c0e40SEric Biggers 		.create_ctx = create_sha256_ctx,
156*b13c0e40SEric Biggers 	},
157*b13c0e40SEric Biggers 	[FS_VERITY_HASH_ALG_SHA512] = {
158*b13c0e40SEric Biggers 		.name = "sha512",
159*b13c0e40SEric Biggers 		.digest_size = 64,
160*b13c0e40SEric Biggers 		.block_size = 128,
161*b13c0e40SEric Biggers 		.create_ctx = create_sha512_ctx,
162*b13c0e40SEric Biggers 	},
163*b13c0e40SEric Biggers };
164*b13c0e40SEric Biggers 
165*b13c0e40SEric Biggers LIBEXPORT u32
libfsverity_find_hash_alg_by_name(const char * name)166*b13c0e40SEric Biggers libfsverity_find_hash_alg_by_name(const char *name)
167*b13c0e40SEric Biggers {
168*b13c0e40SEric Biggers 	int i;
169*b13c0e40SEric Biggers 
170*b13c0e40SEric Biggers 	if (!name)
171*b13c0e40SEric Biggers 		return 0;
172*b13c0e40SEric Biggers 
173*b13c0e40SEric Biggers 	for (i = 1; i < ARRAY_SIZE(fsverity_hash_algs); i++) {
174*b13c0e40SEric Biggers 		if (fsverity_hash_algs[i].name &&
175*b13c0e40SEric Biggers 		    !strcmp(name, fsverity_hash_algs[i].name))
176*b13c0e40SEric Biggers 			return i;
177*b13c0e40SEric Biggers 	}
178*b13c0e40SEric Biggers 	return 0;
179*b13c0e40SEric Biggers }
180*b13c0e40SEric Biggers 
libfsverity_find_hash_alg_by_num(u32 alg_num)181*b13c0e40SEric Biggers const struct fsverity_hash_alg *libfsverity_find_hash_alg_by_num(u32 alg_num)
182*b13c0e40SEric Biggers {
183*b13c0e40SEric Biggers 	if (alg_num < ARRAY_SIZE(fsverity_hash_algs) &&
184*b13c0e40SEric Biggers 	    fsverity_hash_algs[alg_num].name)
185*b13c0e40SEric Biggers 		return &fsverity_hash_algs[alg_num];
186*b13c0e40SEric Biggers 
187*b13c0e40SEric Biggers 	return NULL;
188*b13c0e40SEric Biggers }
189*b13c0e40SEric Biggers 
190*b13c0e40SEric Biggers LIBEXPORT int
libfsverity_get_digest_size(u32 alg_num)191*b13c0e40SEric Biggers libfsverity_get_digest_size(u32 alg_num)
192*b13c0e40SEric Biggers {
193*b13c0e40SEric Biggers 	const struct fsverity_hash_alg *alg =
194*b13c0e40SEric Biggers 		libfsverity_find_hash_alg_by_num(alg_num);
195*b13c0e40SEric Biggers 
196*b13c0e40SEric Biggers 	return alg ? alg->digest_size : -1;
197*b13c0e40SEric Biggers }
198*b13c0e40SEric Biggers 
199*b13c0e40SEric Biggers LIBEXPORT const char *
libfsverity_get_hash_name(u32 alg_num)200*b13c0e40SEric Biggers libfsverity_get_hash_name(u32 alg_num)
201*b13c0e40SEric Biggers {
202*b13c0e40SEric Biggers 	const struct fsverity_hash_alg *alg =
203*b13c0e40SEric Biggers 		libfsverity_find_hash_alg_by_num(alg_num);
204*b13c0e40SEric Biggers 
205*b13c0e40SEric Biggers 	return alg ? alg->name : NULL;
206*b13c0e40SEric Biggers }
207