1cc6ac5d6SJoseph Chen // SPDX-License-Identifier: GPL-2.0 2cc6ac5d6SJoseph Chen /* 3cc6ac5d6SJoseph Chen * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd 4cc6ac5d6SJoseph Chen */ 5cc6ac5d6SJoseph Chen 6cc6ac5d6SJoseph Chen #include <crypto.h> 7cc6ac5d6SJoseph Chen 8*6b5b88bcSLin Jinhan static const u8 null_hash_sha1_value[] = { 9*6b5b88bcSLin Jinhan 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 10*6b5b88bcSLin Jinhan 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 11*6b5b88bcSLin Jinhan 0xaf, 0xd8, 0x07, 0x09 12*6b5b88bcSLin Jinhan }; 13*6b5b88bcSLin Jinhan 14*6b5b88bcSLin Jinhan static const u8 null_hash_md5_value[] = { 15*6b5b88bcSLin Jinhan 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 16*6b5b88bcSLin Jinhan 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e 17*6b5b88bcSLin Jinhan }; 18*6b5b88bcSLin Jinhan 19*6b5b88bcSLin Jinhan static const u8 null_hash_sha256_value[] = { 20*6b5b88bcSLin Jinhan 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 21*6b5b88bcSLin Jinhan 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 22*6b5b88bcSLin Jinhan 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 23*6b5b88bcSLin Jinhan 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 24*6b5b88bcSLin Jinhan }; 25*6b5b88bcSLin Jinhan 26*6b5b88bcSLin Jinhan static const u8 null_hash_sha512_value[] = { 27*6b5b88bcSLin Jinhan 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 28*6b5b88bcSLin Jinhan 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, 29*6b5b88bcSLin Jinhan 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 30*6b5b88bcSLin Jinhan 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 31*6b5b88bcSLin Jinhan 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 32*6b5b88bcSLin Jinhan 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, 33*6b5b88bcSLin Jinhan 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 34*6b5b88bcSLin Jinhan 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e 35*6b5b88bcSLin Jinhan }; 36*6b5b88bcSLin Jinhan 37cc6ac5d6SJoseph Chen u32 crypto_algo_nbits(u32 algo) 38cc6ac5d6SJoseph Chen { 39cc6ac5d6SJoseph Chen switch (algo) { 40cc6ac5d6SJoseph Chen case CRYPTO_MD5: 41cc6ac5d6SJoseph Chen return 128; 42cc6ac5d6SJoseph Chen case CRYPTO_SHA1: 43cc6ac5d6SJoseph Chen return 160; 44cc6ac5d6SJoseph Chen case CRYPTO_SHA256: 45cc6ac5d6SJoseph Chen return 256; 46e7846385SLin Jinhan case CRYPTO_SHA512: 47e7846385SLin Jinhan return 512; 48cc6ac5d6SJoseph Chen case CRYPTO_RSA512: 49cc6ac5d6SJoseph Chen return 512; 50cc6ac5d6SJoseph Chen case CRYPTO_RSA1024: 51cc6ac5d6SJoseph Chen return 1024; 52cc6ac5d6SJoseph Chen case CRYPTO_RSA2048: 53cc6ac5d6SJoseph Chen return 2048; 54b353a43cSLin Jinhan case CRYPTO_RSA3072: 55b353a43cSLin Jinhan return 3072; 56b353a43cSLin Jinhan case CRYPTO_RSA4096: 57b353a43cSLin Jinhan return 4096; 58cc6ac5d6SJoseph Chen } 59cc6ac5d6SJoseph Chen 60cc6ac5d6SJoseph Chen printf("Unknown crypto algorithm: 0x%x\n", algo); 61cc6ac5d6SJoseph Chen 62cc6ac5d6SJoseph Chen return 0; 63cc6ac5d6SJoseph Chen } 64cc6ac5d6SJoseph Chen 65cc6ac5d6SJoseph Chen struct udevice *crypto_get_device(u32 capability) 66cc6ac5d6SJoseph Chen { 67cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops; 68cc6ac5d6SJoseph Chen struct udevice *dev; 69cc6ac5d6SJoseph Chen struct uclass *uc; 70cc6ac5d6SJoseph Chen int ret; 71cc6ac5d6SJoseph Chen u32 cap; 72cc6ac5d6SJoseph Chen 73cc6ac5d6SJoseph Chen ret = uclass_get(UCLASS_CRYPTO, &uc); 74cc6ac5d6SJoseph Chen if (ret) 75cc6ac5d6SJoseph Chen return NULL; 76cc6ac5d6SJoseph Chen 77cc6ac5d6SJoseph Chen for (uclass_first_device(UCLASS_CRYPTO, &dev); 78cc6ac5d6SJoseph Chen dev; 79cc6ac5d6SJoseph Chen uclass_next_device(&dev)) { 80cc6ac5d6SJoseph Chen ops = device_get_ops(dev); 81cc6ac5d6SJoseph Chen if (!ops || !ops->capability) 82cc6ac5d6SJoseph Chen continue; 83cc6ac5d6SJoseph Chen 84cc6ac5d6SJoseph Chen cap = ops->capability(dev); 85cc6ac5d6SJoseph Chen if ((cap & capability) == capability) 86cc6ac5d6SJoseph Chen return dev; 87cc6ac5d6SJoseph Chen } 88cc6ac5d6SJoseph Chen 89cc6ac5d6SJoseph Chen return NULL; 90cc6ac5d6SJoseph Chen } 91cc6ac5d6SJoseph Chen 92cc6ac5d6SJoseph Chen int crypto_sha_init(struct udevice *dev, sha_context *ctx) 93cc6ac5d6SJoseph Chen { 94cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 95cc6ac5d6SJoseph Chen 96*6b5b88bcSLin Jinhan if (ctx && !ctx->length) 97*6b5b88bcSLin Jinhan return 0; 98*6b5b88bcSLin Jinhan 99cc6ac5d6SJoseph Chen if (!ops || !ops->sha_init) 100cc6ac5d6SJoseph Chen return -ENOSYS; 101cc6ac5d6SJoseph Chen 102cc6ac5d6SJoseph Chen return ops->sha_init(dev, ctx); 103cc6ac5d6SJoseph Chen } 104cc6ac5d6SJoseph Chen 105cc6ac5d6SJoseph Chen int crypto_sha_update(struct udevice *dev, u32 *input, u32 len) 106cc6ac5d6SJoseph Chen { 107cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 108cc6ac5d6SJoseph Chen 109*6b5b88bcSLin Jinhan if (!len) 110*6b5b88bcSLin Jinhan return 0; 111*6b5b88bcSLin Jinhan 112cc6ac5d6SJoseph Chen if (!ops || !ops->sha_update) 113cc6ac5d6SJoseph Chen return -ENOSYS; 114cc6ac5d6SJoseph Chen 115cc6ac5d6SJoseph Chen return ops->sha_update(dev, input, len); 116cc6ac5d6SJoseph Chen } 117cc6ac5d6SJoseph Chen 118cc6ac5d6SJoseph Chen int crypto_sha_final(struct udevice *dev, sha_context *ctx, u8 *output) 119cc6ac5d6SJoseph Chen { 120cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 121*6b5b88bcSLin Jinhan const u8 *null_hash = NULL; 122*6b5b88bcSLin Jinhan u32 hash_size = 0; 123*6b5b88bcSLin Jinhan 124*6b5b88bcSLin Jinhan if (ctx && !ctx->length && output) { 125*6b5b88bcSLin Jinhan switch (ctx->algo) { 126*6b5b88bcSLin Jinhan case CRYPTO_MD5: 127*6b5b88bcSLin Jinhan null_hash = null_hash_md5_value; 128*6b5b88bcSLin Jinhan hash_size = sizeof(null_hash_md5_value); 129*6b5b88bcSLin Jinhan break; 130*6b5b88bcSLin Jinhan case CRYPTO_SHA1: 131*6b5b88bcSLin Jinhan null_hash = null_hash_sha1_value; 132*6b5b88bcSLin Jinhan hash_size = sizeof(null_hash_sha1_value); 133*6b5b88bcSLin Jinhan break; 134*6b5b88bcSLin Jinhan case CRYPTO_SHA256: 135*6b5b88bcSLin Jinhan null_hash = null_hash_sha256_value; 136*6b5b88bcSLin Jinhan hash_size = sizeof(null_hash_sha256_value); 137*6b5b88bcSLin Jinhan break; 138*6b5b88bcSLin Jinhan case CRYPTO_SHA512: 139*6b5b88bcSLin Jinhan null_hash = null_hash_sha512_value; 140*6b5b88bcSLin Jinhan hash_size = sizeof(null_hash_sha512_value); 141*6b5b88bcSLin Jinhan break; 142*6b5b88bcSLin Jinhan default: 143*6b5b88bcSLin Jinhan return -EINVAL; 144*6b5b88bcSLin Jinhan } 145*6b5b88bcSLin Jinhan 146*6b5b88bcSLin Jinhan memcpy(output, null_hash, hash_size); 147*6b5b88bcSLin Jinhan 148*6b5b88bcSLin Jinhan return 0; 149*6b5b88bcSLin Jinhan } 150cc6ac5d6SJoseph Chen 151cc6ac5d6SJoseph Chen if (!ops || !ops->sha_final) 152cc6ac5d6SJoseph Chen return -ENOSYS; 153cc6ac5d6SJoseph Chen 154cc6ac5d6SJoseph Chen return ops->sha_final(dev, ctx, output); 155cc6ac5d6SJoseph Chen } 156cc6ac5d6SJoseph Chen 157cc6ac5d6SJoseph Chen int crypto_sha_csum(struct udevice *dev, sha_context *ctx, 158cc6ac5d6SJoseph Chen char *input, u32 input_len, u8 *output) 159cc6ac5d6SJoseph Chen { 160cc6ac5d6SJoseph Chen int ret; 161cc6ac5d6SJoseph Chen 162cc6ac5d6SJoseph Chen ret = crypto_sha_init(dev, ctx); 163cc6ac5d6SJoseph Chen if (ret) 164cc6ac5d6SJoseph Chen return ret; 165cc6ac5d6SJoseph Chen 166cc6ac5d6SJoseph Chen ret = crypto_sha_update(dev, (u32 *)input, input_len); 167cc6ac5d6SJoseph Chen if (ret) 168cc6ac5d6SJoseph Chen return ret; 169cc6ac5d6SJoseph Chen 170cc6ac5d6SJoseph Chen ret = crypto_sha_final(dev, ctx, output); 171cc6ac5d6SJoseph Chen 172cc6ac5d6SJoseph Chen return ret; 173cc6ac5d6SJoseph Chen } 174cc6ac5d6SJoseph Chen 175c14e46abSJoseph Chen int crypto_sha_regions_csum(struct udevice *dev, sha_context *ctx, 176c14e46abSJoseph Chen const struct image_region region[], 177c14e46abSJoseph Chen int region_count, u8 *output) 178c14e46abSJoseph Chen { 179c14e46abSJoseph Chen int i, ret; 180c14e46abSJoseph Chen 181c14e46abSJoseph Chen ctx->length = 0; 182c14e46abSJoseph Chen for (i = 0; i < region_count; i++) 183c14e46abSJoseph Chen ctx->length += region[i].size; 184c14e46abSJoseph Chen 185c14e46abSJoseph Chen ret = crypto_sha_init(dev, ctx); 186c14e46abSJoseph Chen if (ret) 187c14e46abSJoseph Chen return ret; 188c14e46abSJoseph Chen 189c14e46abSJoseph Chen for (i = 0; i < region_count; i++) { 190c14e46abSJoseph Chen ret = crypto_sha_update(dev, (void *)region[i].data, 191c14e46abSJoseph Chen region[i].size); 192c14e46abSJoseph Chen if (ret) 193c14e46abSJoseph Chen return ret; 194c14e46abSJoseph Chen } 195c14e46abSJoseph Chen 196c14e46abSJoseph Chen return crypto_sha_final(dev, ctx, output); 197c14e46abSJoseph Chen } 198c14e46abSJoseph Chen 199cc6ac5d6SJoseph Chen int crypto_rsa_verify(struct udevice *dev, rsa_key *ctx, u8 *sign, u8 *output) 200cc6ac5d6SJoseph Chen { 201cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 202cc6ac5d6SJoseph Chen 203cc6ac5d6SJoseph Chen if (!ops || !ops->rsa_verify) 204cc6ac5d6SJoseph Chen return -ENOSYS; 205cc6ac5d6SJoseph Chen 206cc6ac5d6SJoseph Chen return ops->rsa_verify(dev, ctx, sign, output); 207cc6ac5d6SJoseph Chen } 208cc6ac5d6SJoseph Chen 209434d6fd3SLin Jinhan int crypto_get_trng(struct udevice *dev, u8 *output, u32 len) 210434d6fd3SLin Jinhan { 211434d6fd3SLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 212434d6fd3SLin Jinhan 213434d6fd3SLin Jinhan if (!ops || !ops->get_trng) 214434d6fd3SLin Jinhan return -ENOSYS; 215434d6fd3SLin Jinhan 216434d6fd3SLin Jinhan return ops->get_trng(dev, output, len); 217434d6fd3SLin Jinhan } 218434d6fd3SLin Jinhan 219cc6ac5d6SJoseph Chen UCLASS_DRIVER(crypto) = { 220cc6ac5d6SJoseph Chen .id = UCLASS_CRYPTO, 221cc6ac5d6SJoseph Chen .name = "crypto", 222cc6ac5d6SJoseph Chen }; 223