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 86b5b88bcSLin Jinhan static const u8 null_hash_sha1_value[] = { 96b5b88bcSLin Jinhan 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 106b5b88bcSLin Jinhan 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 116b5b88bcSLin Jinhan 0xaf, 0xd8, 0x07, 0x09 126b5b88bcSLin Jinhan }; 136b5b88bcSLin Jinhan 146b5b88bcSLin Jinhan static const u8 null_hash_md5_value[] = { 156b5b88bcSLin Jinhan 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 166b5b88bcSLin Jinhan 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e 176b5b88bcSLin Jinhan }; 186b5b88bcSLin Jinhan 196b5b88bcSLin Jinhan static const u8 null_hash_sha256_value[] = { 206b5b88bcSLin Jinhan 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 216b5b88bcSLin Jinhan 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 226b5b88bcSLin Jinhan 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 236b5b88bcSLin Jinhan 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 246b5b88bcSLin Jinhan }; 256b5b88bcSLin Jinhan 266b5b88bcSLin Jinhan static const u8 null_hash_sha512_value[] = { 276b5b88bcSLin Jinhan 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 286b5b88bcSLin Jinhan 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, 296b5b88bcSLin Jinhan 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 306b5b88bcSLin Jinhan 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 316b5b88bcSLin Jinhan 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 326b5b88bcSLin Jinhan 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, 336b5b88bcSLin Jinhan 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 346b5b88bcSLin Jinhan 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e 356b5b88bcSLin Jinhan }; 366b5b88bcSLin Jinhan 3749a2135eSLin Jinhan const static u8 null_hash_sm3_value[] = { 3849a2135eSLin Jinhan 0x1a, 0xb2, 0x1d, 0x83, 0x55, 0xcf, 0xa1, 0x7f, 3949a2135eSLin Jinhan 0x8e, 0x61, 0x19, 0x48, 0x31, 0xe8, 0x1a, 0x8f, 4049a2135eSLin Jinhan 0x22, 0xbe, 0xc8, 0xc7, 0x28, 0xfe, 0xfb, 0x74, 4149a2135eSLin Jinhan 0x7e, 0xd0, 0x35, 0xeb, 0x50, 0x82, 0xaa, 0x2b 4249a2135eSLin Jinhan }; 4349a2135eSLin Jinhan 44cc6ac5d6SJoseph Chen u32 crypto_algo_nbits(u32 algo) 45cc6ac5d6SJoseph Chen { 46cc6ac5d6SJoseph Chen switch (algo) { 47cc6ac5d6SJoseph Chen case CRYPTO_MD5: 4849a2135eSLin Jinhan case CRYPTO_HMAC_MD5: 49cc6ac5d6SJoseph Chen return 128; 50cc6ac5d6SJoseph Chen case CRYPTO_SHA1: 5149a2135eSLin Jinhan case CRYPTO_HMAC_SHA1: 52cc6ac5d6SJoseph Chen return 160; 53cc6ac5d6SJoseph Chen case CRYPTO_SHA256: 5449a2135eSLin Jinhan case CRYPTO_HMAC_SHA256: 55cc6ac5d6SJoseph Chen return 256; 56e7846385SLin Jinhan case CRYPTO_SHA512: 5749a2135eSLin Jinhan case CRYPTO_HMAC_SHA512: 58e7846385SLin Jinhan return 512; 5949a2135eSLin Jinhan case CRYPTO_SM3: 6049a2135eSLin Jinhan case CRYPTO_HMAC_SM3: 6149a2135eSLin Jinhan return 256; 62cc6ac5d6SJoseph Chen case CRYPTO_RSA512: 63cc6ac5d6SJoseph Chen return 512; 64cc6ac5d6SJoseph Chen case CRYPTO_RSA1024: 65cc6ac5d6SJoseph Chen return 1024; 66cc6ac5d6SJoseph Chen case CRYPTO_RSA2048: 67cc6ac5d6SJoseph Chen return 2048; 68b353a43cSLin Jinhan case CRYPTO_RSA3072: 69b353a43cSLin Jinhan return 3072; 70b353a43cSLin Jinhan case CRYPTO_RSA4096: 71b353a43cSLin Jinhan return 4096; 72cc6ac5d6SJoseph Chen } 73cc6ac5d6SJoseph Chen 74cc6ac5d6SJoseph Chen printf("Unknown crypto algorithm: 0x%x\n", algo); 75cc6ac5d6SJoseph Chen 76cc6ac5d6SJoseph Chen return 0; 77cc6ac5d6SJoseph Chen } 78cc6ac5d6SJoseph Chen 79cc6ac5d6SJoseph Chen struct udevice *crypto_get_device(u32 capability) 80cc6ac5d6SJoseph Chen { 81cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops; 82cc6ac5d6SJoseph Chen struct udevice *dev; 83cc6ac5d6SJoseph Chen struct uclass *uc; 84cc6ac5d6SJoseph Chen int ret; 85cc6ac5d6SJoseph Chen u32 cap; 86cc6ac5d6SJoseph Chen 87cc6ac5d6SJoseph Chen ret = uclass_get(UCLASS_CRYPTO, &uc); 88cc6ac5d6SJoseph Chen if (ret) 89cc6ac5d6SJoseph Chen return NULL; 90cc6ac5d6SJoseph Chen 91cc6ac5d6SJoseph Chen for (uclass_first_device(UCLASS_CRYPTO, &dev); 92cc6ac5d6SJoseph Chen dev; 93cc6ac5d6SJoseph Chen uclass_next_device(&dev)) { 94cc6ac5d6SJoseph Chen ops = device_get_ops(dev); 95cc6ac5d6SJoseph Chen if (!ops || !ops->capability) 96cc6ac5d6SJoseph Chen continue; 97cc6ac5d6SJoseph Chen 98cc6ac5d6SJoseph Chen cap = ops->capability(dev); 99cc6ac5d6SJoseph Chen if ((cap & capability) == capability) 100cc6ac5d6SJoseph Chen return dev; 101cc6ac5d6SJoseph Chen } 102cc6ac5d6SJoseph Chen 103cc6ac5d6SJoseph Chen return NULL; 104cc6ac5d6SJoseph Chen } 105cc6ac5d6SJoseph Chen 106cc6ac5d6SJoseph Chen int crypto_sha_init(struct udevice *dev, sha_context *ctx) 107cc6ac5d6SJoseph Chen { 108cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 109cc6ac5d6SJoseph Chen 1106b5b88bcSLin Jinhan if (ctx && !ctx->length) 1116b5b88bcSLin Jinhan return 0; 1126b5b88bcSLin Jinhan 113cc6ac5d6SJoseph Chen if (!ops || !ops->sha_init) 114cc6ac5d6SJoseph Chen return -ENOSYS; 115cc6ac5d6SJoseph Chen 116cc6ac5d6SJoseph Chen return ops->sha_init(dev, ctx); 117cc6ac5d6SJoseph Chen } 118cc6ac5d6SJoseph Chen 119cc6ac5d6SJoseph Chen int crypto_sha_update(struct udevice *dev, u32 *input, u32 len) 120cc6ac5d6SJoseph Chen { 121cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 122cc6ac5d6SJoseph Chen 1236b5b88bcSLin Jinhan if (!len) 1246b5b88bcSLin Jinhan return 0; 1256b5b88bcSLin Jinhan 126cc6ac5d6SJoseph Chen if (!ops || !ops->sha_update) 127cc6ac5d6SJoseph Chen return -ENOSYS; 128cc6ac5d6SJoseph Chen 129cc6ac5d6SJoseph Chen return ops->sha_update(dev, input, len); 130cc6ac5d6SJoseph Chen } 131cc6ac5d6SJoseph Chen 132cc6ac5d6SJoseph Chen int crypto_sha_final(struct udevice *dev, sha_context *ctx, u8 *output) 133cc6ac5d6SJoseph Chen { 134cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 1356b5b88bcSLin Jinhan const u8 *null_hash = NULL; 1366b5b88bcSLin Jinhan u32 hash_size = 0; 1376b5b88bcSLin Jinhan 1386b5b88bcSLin Jinhan if (ctx && !ctx->length && output) { 1396b5b88bcSLin Jinhan switch (ctx->algo) { 1406b5b88bcSLin Jinhan case CRYPTO_MD5: 1416b5b88bcSLin Jinhan null_hash = null_hash_md5_value; 1426b5b88bcSLin Jinhan hash_size = sizeof(null_hash_md5_value); 1436b5b88bcSLin Jinhan break; 1446b5b88bcSLin Jinhan case CRYPTO_SHA1: 1456b5b88bcSLin Jinhan null_hash = null_hash_sha1_value; 1466b5b88bcSLin Jinhan hash_size = sizeof(null_hash_sha1_value); 1476b5b88bcSLin Jinhan break; 1486b5b88bcSLin Jinhan case CRYPTO_SHA256: 1496b5b88bcSLin Jinhan null_hash = null_hash_sha256_value; 1506b5b88bcSLin Jinhan hash_size = sizeof(null_hash_sha256_value); 1516b5b88bcSLin Jinhan break; 1526b5b88bcSLin Jinhan case CRYPTO_SHA512: 1536b5b88bcSLin Jinhan null_hash = null_hash_sha512_value; 1546b5b88bcSLin Jinhan hash_size = sizeof(null_hash_sha512_value); 1556b5b88bcSLin Jinhan break; 15649a2135eSLin Jinhan case CRYPTO_SM3: 15749a2135eSLin Jinhan null_hash = null_hash_sm3_value; 15849a2135eSLin Jinhan hash_size = sizeof(null_hash_sm3_value); 15949a2135eSLin Jinhan break; 1606b5b88bcSLin Jinhan default: 1616b5b88bcSLin Jinhan return -EINVAL; 1626b5b88bcSLin Jinhan } 1636b5b88bcSLin Jinhan 1646b5b88bcSLin Jinhan memcpy(output, null_hash, hash_size); 1656b5b88bcSLin Jinhan 1666b5b88bcSLin Jinhan return 0; 1676b5b88bcSLin Jinhan } 168cc6ac5d6SJoseph Chen 169cc6ac5d6SJoseph Chen if (!ops || !ops->sha_final) 170cc6ac5d6SJoseph Chen return -ENOSYS; 171cc6ac5d6SJoseph Chen 172cc6ac5d6SJoseph Chen return ops->sha_final(dev, ctx, output); 173cc6ac5d6SJoseph Chen } 174cc6ac5d6SJoseph Chen 17549a2135eSLin Jinhan int crypto_hmac_init(struct udevice *dev, sha_context *ctx, 17649a2135eSLin Jinhan u8 *key, u32 key_len) 17749a2135eSLin Jinhan { 17849a2135eSLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 17949a2135eSLin Jinhan 18049a2135eSLin Jinhan if (ctx && !ctx->length) 18149a2135eSLin Jinhan return -EINVAL; 18249a2135eSLin Jinhan 18349a2135eSLin Jinhan if (!ops || !ops->hmac_init) 18449a2135eSLin Jinhan return -ENOSYS; 18549a2135eSLin Jinhan 18649a2135eSLin Jinhan return ops->hmac_init(dev, ctx, key, key_len); 18749a2135eSLin Jinhan } 18849a2135eSLin Jinhan 18949a2135eSLin Jinhan int crypto_hmac_update(struct udevice *dev, u32 *input, u32 len) 19049a2135eSLin Jinhan { 19149a2135eSLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 19249a2135eSLin Jinhan 19349a2135eSLin Jinhan if (!len) 19449a2135eSLin Jinhan return 0; 19549a2135eSLin Jinhan 19649a2135eSLin Jinhan if (!ops || !ops->hmac_update) 19749a2135eSLin Jinhan return -ENOSYS; 19849a2135eSLin Jinhan 19949a2135eSLin Jinhan return ops->hmac_update(dev, input, len); 20049a2135eSLin Jinhan } 20149a2135eSLin Jinhan 20249a2135eSLin Jinhan int crypto_hmac_final(struct udevice *dev, sha_context *ctx, u8 *output) 20349a2135eSLin Jinhan { 20449a2135eSLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 20549a2135eSLin Jinhan 20649a2135eSLin Jinhan if (!ops || !ops->hmac_final) 20749a2135eSLin Jinhan return -ENOSYS; 20849a2135eSLin Jinhan 20949a2135eSLin Jinhan return ops->hmac_final(dev, ctx, output); 21049a2135eSLin Jinhan } 21149a2135eSLin Jinhan 212cc6ac5d6SJoseph Chen int crypto_sha_csum(struct udevice *dev, sha_context *ctx, 213cc6ac5d6SJoseph Chen char *input, u32 input_len, u8 *output) 214cc6ac5d6SJoseph Chen { 215cc6ac5d6SJoseph Chen int ret; 216cc6ac5d6SJoseph Chen 217cc6ac5d6SJoseph Chen ret = crypto_sha_init(dev, ctx); 218cc6ac5d6SJoseph Chen if (ret) 219cc6ac5d6SJoseph Chen return ret; 220cc6ac5d6SJoseph Chen 221cc6ac5d6SJoseph Chen ret = crypto_sha_update(dev, (u32 *)input, input_len); 222cc6ac5d6SJoseph Chen if (ret) 223cc6ac5d6SJoseph Chen return ret; 224cc6ac5d6SJoseph Chen 225cc6ac5d6SJoseph Chen ret = crypto_sha_final(dev, ctx, output); 226cc6ac5d6SJoseph Chen 227cc6ac5d6SJoseph Chen return ret; 228cc6ac5d6SJoseph Chen } 229cc6ac5d6SJoseph Chen 230c14e46abSJoseph Chen int crypto_sha_regions_csum(struct udevice *dev, sha_context *ctx, 231c14e46abSJoseph Chen const struct image_region region[], 232c14e46abSJoseph Chen int region_count, u8 *output) 233c14e46abSJoseph Chen { 234c14e46abSJoseph Chen int i, ret; 235c14e46abSJoseph Chen 236c14e46abSJoseph Chen ctx->length = 0; 237c14e46abSJoseph Chen for (i = 0; i < region_count; i++) 238c14e46abSJoseph Chen ctx->length += region[i].size; 239c14e46abSJoseph Chen 240c14e46abSJoseph Chen ret = crypto_sha_init(dev, ctx); 241c14e46abSJoseph Chen if (ret) 242c14e46abSJoseph Chen return ret; 243c14e46abSJoseph Chen 244c14e46abSJoseph Chen for (i = 0; i < region_count; i++) { 245c14e46abSJoseph Chen ret = crypto_sha_update(dev, (void *)region[i].data, 246c14e46abSJoseph Chen region[i].size); 247c14e46abSJoseph Chen if (ret) 248c14e46abSJoseph Chen return ret; 249c14e46abSJoseph Chen } 250c14e46abSJoseph Chen 251c14e46abSJoseph Chen return crypto_sha_final(dev, ctx, output); 252c14e46abSJoseph Chen } 253c14e46abSJoseph Chen 254cc6ac5d6SJoseph Chen int crypto_rsa_verify(struct udevice *dev, rsa_key *ctx, u8 *sign, u8 *output) 255cc6ac5d6SJoseph Chen { 256cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 257cc6ac5d6SJoseph Chen 258cc6ac5d6SJoseph Chen if (!ops || !ops->rsa_verify) 259cc6ac5d6SJoseph Chen return -ENOSYS; 260cc6ac5d6SJoseph Chen 261cc6ac5d6SJoseph Chen return ops->rsa_verify(dev, ctx, sign, output); 262cc6ac5d6SJoseph Chen } 263cc6ac5d6SJoseph Chen 26449a2135eSLin Jinhan int crypto_cipher(struct udevice *dev, cipher_context *ctx, 26549a2135eSLin Jinhan const u8 *in, u8 *out, u32 len, bool enc) 26649a2135eSLin Jinhan { 26749a2135eSLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 26849a2135eSLin Jinhan 26949a2135eSLin Jinhan if (!ops || !ops->cipher_crypt) 27049a2135eSLin Jinhan return -ENOSYS; 27149a2135eSLin Jinhan 27249a2135eSLin Jinhan return ops->cipher_crypt(dev, ctx, in, out, len, enc); 27349a2135eSLin Jinhan } 27449a2135eSLin Jinhan 275d9332f1cSLin Jinhan int crypto_mac(struct udevice *dev, cipher_context *ctx, 276d9332f1cSLin Jinhan const u8 *in, u32 len, u8 *tag) 277d9332f1cSLin Jinhan { 278d9332f1cSLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 279d9332f1cSLin Jinhan 280d9332f1cSLin Jinhan if (!ops || !ops->cipher_mac) 281d9332f1cSLin Jinhan return -ENOSYS; 282d9332f1cSLin Jinhan 283d9332f1cSLin Jinhan return ops->cipher_mac(dev, ctx, in, len, tag); 284d9332f1cSLin Jinhan } 285d9332f1cSLin Jinhan 286*c3ce9937SLin Jinhan int crypto_ae(struct udevice *dev, cipher_context *ctx, 287*c3ce9937SLin Jinhan const u8 *in, u32 len, const u8 *aad, u32 aad_len, 288*c3ce9937SLin Jinhan u8 *out, u8 *tag) 289*c3ce9937SLin Jinhan { 290*c3ce9937SLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 291*c3ce9937SLin Jinhan 292*c3ce9937SLin Jinhan if (!ops || !ops->cipher_ae) 293*c3ce9937SLin Jinhan return -ENOSYS; 294*c3ce9937SLin Jinhan 295*c3ce9937SLin Jinhan return ops->cipher_ae(dev, ctx, in, len, aad, aad_len, out, tag); 296*c3ce9937SLin Jinhan } 297*c3ce9937SLin Jinhan 298cc6ac5d6SJoseph Chen UCLASS_DRIVER(crypto) = { 299cc6ac5d6SJoseph Chen .id = UCLASS_CRYPTO, 300cc6ac5d6SJoseph Chen .name = "crypto", 301cc6ac5d6SJoseph Chen }; 302