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; 72*02b4cf42SLin Jinhan case CRYPTO_SM2: 73*02b4cf42SLin Jinhan return 256; 74*02b4cf42SLin Jinhan case CRYPTO_ECC_192R1: 75*02b4cf42SLin Jinhan return 192; 76*02b4cf42SLin Jinhan case CRYPTO_ECC_224R1: 77*02b4cf42SLin Jinhan return 224; 78*02b4cf42SLin Jinhan case CRYPTO_ECC_256R1: 79*02b4cf42SLin Jinhan return 256; 80cc6ac5d6SJoseph Chen } 81cc6ac5d6SJoseph Chen 82cc6ac5d6SJoseph Chen printf("Unknown crypto algorithm: 0x%x\n", algo); 83cc6ac5d6SJoseph Chen 84cc6ac5d6SJoseph Chen return 0; 85cc6ac5d6SJoseph Chen } 86cc6ac5d6SJoseph Chen 87cc6ac5d6SJoseph Chen struct udevice *crypto_get_device(u32 capability) 88cc6ac5d6SJoseph Chen { 89cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops; 90cc6ac5d6SJoseph Chen struct udevice *dev; 91cc6ac5d6SJoseph Chen struct uclass *uc; 92cc6ac5d6SJoseph Chen int ret; 93cc6ac5d6SJoseph Chen u32 cap; 94cc6ac5d6SJoseph Chen 95cc6ac5d6SJoseph Chen ret = uclass_get(UCLASS_CRYPTO, &uc); 96cc6ac5d6SJoseph Chen if (ret) 97cc6ac5d6SJoseph Chen return NULL; 98cc6ac5d6SJoseph Chen 99cc6ac5d6SJoseph Chen for (uclass_first_device(UCLASS_CRYPTO, &dev); 100cc6ac5d6SJoseph Chen dev; 101cc6ac5d6SJoseph Chen uclass_next_device(&dev)) { 102cc6ac5d6SJoseph Chen ops = device_get_ops(dev); 103cc6ac5d6SJoseph Chen if (!ops || !ops->capability) 104cc6ac5d6SJoseph Chen continue; 105cc6ac5d6SJoseph Chen 106cc6ac5d6SJoseph Chen cap = ops->capability(dev); 107cc6ac5d6SJoseph Chen if ((cap & capability) == capability) 108cc6ac5d6SJoseph Chen return dev; 109cc6ac5d6SJoseph Chen } 110cc6ac5d6SJoseph Chen 111cc6ac5d6SJoseph Chen return NULL; 112cc6ac5d6SJoseph Chen } 113cc6ac5d6SJoseph Chen 114cc6ac5d6SJoseph Chen int crypto_sha_init(struct udevice *dev, sha_context *ctx) 115cc6ac5d6SJoseph Chen { 116cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 117cc6ac5d6SJoseph Chen 1186b5b88bcSLin Jinhan if (ctx && !ctx->length) 1196b5b88bcSLin Jinhan return 0; 1206b5b88bcSLin Jinhan 121cc6ac5d6SJoseph Chen if (!ops || !ops->sha_init) 122cc6ac5d6SJoseph Chen return -ENOSYS; 123cc6ac5d6SJoseph Chen 124cc6ac5d6SJoseph Chen return ops->sha_init(dev, ctx); 125cc6ac5d6SJoseph Chen } 126cc6ac5d6SJoseph Chen 127cc6ac5d6SJoseph Chen int crypto_sha_update(struct udevice *dev, u32 *input, u32 len) 128cc6ac5d6SJoseph Chen { 129cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 130cc6ac5d6SJoseph Chen 1316b5b88bcSLin Jinhan if (!len) 1326b5b88bcSLin Jinhan return 0; 1336b5b88bcSLin Jinhan 134cc6ac5d6SJoseph Chen if (!ops || !ops->sha_update) 135cc6ac5d6SJoseph Chen return -ENOSYS; 136cc6ac5d6SJoseph Chen 137cc6ac5d6SJoseph Chen return ops->sha_update(dev, input, len); 138cc6ac5d6SJoseph Chen } 139cc6ac5d6SJoseph Chen 140cc6ac5d6SJoseph Chen int crypto_sha_final(struct udevice *dev, sha_context *ctx, u8 *output) 141cc6ac5d6SJoseph Chen { 142cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 1436b5b88bcSLin Jinhan const u8 *null_hash = NULL; 1446b5b88bcSLin Jinhan u32 hash_size = 0; 1456b5b88bcSLin Jinhan 1466b5b88bcSLin Jinhan if (ctx && !ctx->length && output) { 1476b5b88bcSLin Jinhan switch (ctx->algo) { 1486b5b88bcSLin Jinhan case CRYPTO_MD5: 1496b5b88bcSLin Jinhan null_hash = null_hash_md5_value; 1506b5b88bcSLin Jinhan hash_size = sizeof(null_hash_md5_value); 1516b5b88bcSLin Jinhan break; 1526b5b88bcSLin Jinhan case CRYPTO_SHA1: 1536b5b88bcSLin Jinhan null_hash = null_hash_sha1_value; 1546b5b88bcSLin Jinhan hash_size = sizeof(null_hash_sha1_value); 1556b5b88bcSLin Jinhan break; 1566b5b88bcSLin Jinhan case CRYPTO_SHA256: 1576b5b88bcSLin Jinhan null_hash = null_hash_sha256_value; 1586b5b88bcSLin Jinhan hash_size = sizeof(null_hash_sha256_value); 1596b5b88bcSLin Jinhan break; 1606b5b88bcSLin Jinhan case CRYPTO_SHA512: 1616b5b88bcSLin Jinhan null_hash = null_hash_sha512_value; 1626b5b88bcSLin Jinhan hash_size = sizeof(null_hash_sha512_value); 1636b5b88bcSLin Jinhan break; 16449a2135eSLin Jinhan case CRYPTO_SM3: 16549a2135eSLin Jinhan null_hash = null_hash_sm3_value; 16649a2135eSLin Jinhan hash_size = sizeof(null_hash_sm3_value); 16749a2135eSLin Jinhan break; 1686b5b88bcSLin Jinhan default: 1696b5b88bcSLin Jinhan return -EINVAL; 1706b5b88bcSLin Jinhan } 1716b5b88bcSLin Jinhan 1726b5b88bcSLin Jinhan memcpy(output, null_hash, hash_size); 1736b5b88bcSLin Jinhan 1746b5b88bcSLin Jinhan return 0; 1756b5b88bcSLin Jinhan } 176cc6ac5d6SJoseph Chen 177cc6ac5d6SJoseph Chen if (!ops || !ops->sha_final) 178cc6ac5d6SJoseph Chen return -ENOSYS; 179cc6ac5d6SJoseph Chen 180cc6ac5d6SJoseph Chen return ops->sha_final(dev, ctx, output); 181cc6ac5d6SJoseph Chen } 182cc6ac5d6SJoseph Chen 18349a2135eSLin Jinhan int crypto_hmac_init(struct udevice *dev, sha_context *ctx, 18449a2135eSLin Jinhan u8 *key, u32 key_len) 18549a2135eSLin Jinhan { 18649a2135eSLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 18749a2135eSLin Jinhan 18849a2135eSLin Jinhan if (ctx && !ctx->length) 18949a2135eSLin Jinhan return -EINVAL; 19049a2135eSLin Jinhan 19149a2135eSLin Jinhan if (!ops || !ops->hmac_init) 19249a2135eSLin Jinhan return -ENOSYS; 19349a2135eSLin Jinhan 19449a2135eSLin Jinhan return ops->hmac_init(dev, ctx, key, key_len); 19549a2135eSLin Jinhan } 19649a2135eSLin Jinhan 19749a2135eSLin Jinhan int crypto_hmac_update(struct udevice *dev, u32 *input, u32 len) 19849a2135eSLin Jinhan { 19949a2135eSLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 20049a2135eSLin Jinhan 20149a2135eSLin Jinhan if (!len) 20249a2135eSLin Jinhan return 0; 20349a2135eSLin Jinhan 20449a2135eSLin Jinhan if (!ops || !ops->hmac_update) 20549a2135eSLin Jinhan return -ENOSYS; 20649a2135eSLin Jinhan 20749a2135eSLin Jinhan return ops->hmac_update(dev, input, len); 20849a2135eSLin Jinhan } 20949a2135eSLin Jinhan 21049a2135eSLin Jinhan int crypto_hmac_final(struct udevice *dev, sha_context *ctx, u8 *output) 21149a2135eSLin Jinhan { 21249a2135eSLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 21349a2135eSLin Jinhan 21449a2135eSLin Jinhan if (!ops || !ops->hmac_final) 21549a2135eSLin Jinhan return -ENOSYS; 21649a2135eSLin Jinhan 21749a2135eSLin Jinhan return ops->hmac_final(dev, ctx, output); 21849a2135eSLin Jinhan } 21949a2135eSLin Jinhan 220cc6ac5d6SJoseph Chen int crypto_sha_csum(struct udevice *dev, sha_context *ctx, 221cc6ac5d6SJoseph Chen char *input, u32 input_len, u8 *output) 222cc6ac5d6SJoseph Chen { 223cc6ac5d6SJoseph Chen int ret; 224cc6ac5d6SJoseph Chen 225cc6ac5d6SJoseph Chen ret = crypto_sha_init(dev, ctx); 226cc6ac5d6SJoseph Chen if (ret) 227cc6ac5d6SJoseph Chen return ret; 228cc6ac5d6SJoseph Chen 229cc6ac5d6SJoseph Chen ret = crypto_sha_update(dev, (u32 *)input, input_len); 230cc6ac5d6SJoseph Chen if (ret) 231cc6ac5d6SJoseph Chen return ret; 232cc6ac5d6SJoseph Chen 233cc6ac5d6SJoseph Chen ret = crypto_sha_final(dev, ctx, output); 234cc6ac5d6SJoseph Chen 235cc6ac5d6SJoseph Chen return ret; 236cc6ac5d6SJoseph Chen } 237cc6ac5d6SJoseph Chen 238c14e46abSJoseph Chen int crypto_sha_regions_csum(struct udevice *dev, sha_context *ctx, 239c14e46abSJoseph Chen const struct image_region region[], 240c14e46abSJoseph Chen int region_count, u8 *output) 241c14e46abSJoseph Chen { 242c14e46abSJoseph Chen int i, ret; 243c14e46abSJoseph Chen 244c14e46abSJoseph Chen ctx->length = 0; 245c14e46abSJoseph Chen for (i = 0; i < region_count; i++) 246c14e46abSJoseph Chen ctx->length += region[i].size; 247c14e46abSJoseph Chen 248c14e46abSJoseph Chen ret = crypto_sha_init(dev, ctx); 249c14e46abSJoseph Chen if (ret) 250c14e46abSJoseph Chen return ret; 251c14e46abSJoseph Chen 252c14e46abSJoseph Chen for (i = 0; i < region_count; i++) { 253c14e46abSJoseph Chen ret = crypto_sha_update(dev, (void *)region[i].data, 254c14e46abSJoseph Chen region[i].size); 255c14e46abSJoseph Chen if (ret) 256c14e46abSJoseph Chen return ret; 257c14e46abSJoseph Chen } 258c14e46abSJoseph Chen 259c14e46abSJoseph Chen return crypto_sha_final(dev, ctx, output); 260c14e46abSJoseph Chen } 261c14e46abSJoseph Chen 262cc6ac5d6SJoseph Chen int crypto_rsa_verify(struct udevice *dev, rsa_key *ctx, u8 *sign, u8 *output) 263cc6ac5d6SJoseph Chen { 264cc6ac5d6SJoseph Chen const struct dm_crypto_ops *ops = device_get_ops(dev); 265cc6ac5d6SJoseph Chen 266cc6ac5d6SJoseph Chen if (!ops || !ops->rsa_verify) 267cc6ac5d6SJoseph Chen return -ENOSYS; 268cc6ac5d6SJoseph Chen 269549a74f7SLin Jinhan if (!ctx || !ctx->n || !ctx->e || !sign || !output) 270549a74f7SLin Jinhan return -EINVAL; 271549a74f7SLin Jinhan 272cc6ac5d6SJoseph Chen return ops->rsa_verify(dev, ctx, sign, output); 273cc6ac5d6SJoseph Chen } 274cc6ac5d6SJoseph Chen 275*02b4cf42SLin Jinhan int crypto_ec_verify(struct udevice *dev, ec_key *ctx, u8 *hash, u32 hash_len, u8 *sign) 276*02b4cf42SLin Jinhan { 277*02b4cf42SLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 278*02b4cf42SLin Jinhan 279*02b4cf42SLin Jinhan if (!ops || !ops->ec_verify) 280*02b4cf42SLin Jinhan return -ENOSYS; 281*02b4cf42SLin Jinhan 282*02b4cf42SLin Jinhan if (!ctx || !ctx->x || !ctx->y || !ctx->y || !hash || hash_len == 0 || !sign) 283*02b4cf42SLin Jinhan return -EINVAL; 284*02b4cf42SLin Jinhan 285*02b4cf42SLin Jinhan return ops->ec_verify(dev, ctx, hash, hash_len, sign); 286*02b4cf42SLin Jinhan } 287*02b4cf42SLin Jinhan 28849a2135eSLin Jinhan int crypto_cipher(struct udevice *dev, cipher_context *ctx, 28949a2135eSLin Jinhan const u8 *in, u8 *out, u32 len, bool enc) 29049a2135eSLin Jinhan { 29149a2135eSLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 29249a2135eSLin Jinhan 29349a2135eSLin Jinhan if (!ops || !ops->cipher_crypt) 29449a2135eSLin Jinhan return -ENOSYS; 29549a2135eSLin Jinhan 29649a2135eSLin Jinhan return ops->cipher_crypt(dev, ctx, in, out, len, enc); 29749a2135eSLin Jinhan } 29849a2135eSLin Jinhan 299d9332f1cSLin Jinhan int crypto_mac(struct udevice *dev, cipher_context *ctx, 300d9332f1cSLin Jinhan const u8 *in, u32 len, u8 *tag) 301d9332f1cSLin Jinhan { 302d9332f1cSLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 303d9332f1cSLin Jinhan 304d9332f1cSLin Jinhan if (!ops || !ops->cipher_mac) 305d9332f1cSLin Jinhan return -ENOSYS; 306d9332f1cSLin Jinhan 307d9332f1cSLin Jinhan return ops->cipher_mac(dev, ctx, in, len, tag); 308d9332f1cSLin Jinhan } 309d9332f1cSLin Jinhan 310c3ce9937SLin Jinhan int crypto_ae(struct udevice *dev, cipher_context *ctx, 311c3ce9937SLin Jinhan const u8 *in, u32 len, const u8 *aad, u32 aad_len, 312c3ce9937SLin Jinhan u8 *out, u8 *tag) 313c3ce9937SLin Jinhan { 314c3ce9937SLin Jinhan const struct dm_crypto_ops *ops = device_get_ops(dev); 315c3ce9937SLin Jinhan 316c3ce9937SLin Jinhan if (!ops || !ops->cipher_ae) 317c3ce9937SLin Jinhan return -ENOSYS; 318c3ce9937SLin Jinhan 319c3ce9937SLin Jinhan return ops->cipher_ae(dev, ctx, in, len, aad, aad_len, out, tag); 320c3ce9937SLin Jinhan } 321c3ce9937SLin Jinhan 322cc6ac5d6SJoseph Chen UCLASS_DRIVER(crypto) = { 323cc6ac5d6SJoseph Chen .id = UCLASS_CRYPTO, 324cc6ac5d6SJoseph Chen .name = "crypto", 325cc6ac5d6SJoseph Chen }; 326