crypto/asymmetric_keys/public_key.c

Source file repositories/reference/linux-study-clean/crypto/asymmetric_keys/public_key.c

File Facts

System
Linux kernel
Corpus path
crypto/asymmetric_keys/public_key.c
Extension
.c
Size
12201 bytes
Lines
472
Domain
Kernel Services
Bucket
crypto
Inferred role
Kernel Services: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

if (strcmp(encoding, "pkcs1") == 0) {
			*sig = op == kernel_pkey_sign ||
			       op == kernel_pkey_verify;
			if (!*sig) {
				/*
				 * For encrypt/decrypt, hash_algo is not used
				 * but allowed to be set for historic reasons.
				 */
				n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
					     "pkcs1pad(%s)",
					     pkey->pkey_algo);
			} else {
				if (!hash_algo)
					hash_algo = "none";
				n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
					     "pkcs1(%s,%s)",
					     pkey->pkey_algo, hash_algo);
			}
			return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
		}
		if (strcmp(encoding, "raw") != 0)
			return -EINVAL;
		/*
		 * Raw RSA cannot differentiate between different hash
		 * algorithms.
		 */
		if (hash_algo)
			return -EINVAL;
		*sig = false;
	} else if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) {
		if (strcmp(encoding, "x962") != 0 &&
		    strcmp(encoding, "p1363") != 0)
			return -EINVAL;
		/*
		 * ECDSA signatures are taken over a raw hash, so they don't
		 * differentiate between different hash algorithms.  That means
		 * that the verifier should hard-code a specific hash algorithm.
		 * Unfortunately, in practice ECDSA is used with multiple SHAs,
		 * so we have to allow all of them and not just one.
		 */
		if (!hash_algo)
			return -EINVAL;
		if (strcmp(hash_algo, "sha1") != 0 &&
		    strcmp(hash_algo, "sha224") != 0 &&
		    strcmp(hash_algo, "sha256") != 0 &&
		    strcmp(hash_algo, "sha384") != 0 &&
		    strcmp(hash_algo, "sha512") != 0 &&
		    strcmp(hash_algo, "sha3-256") != 0 &&
		    strcmp(hash_algo, "sha3-384") != 0 &&
		    strcmp(hash_algo, "sha3-512") != 0)
			return -EINVAL;
		n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
			     encoding, pkey->pkey_algo);
		return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
	} else if (strcmp(pkey->pkey_algo, "ecrdsa") == 0) {
		if (strcmp(encoding, "raw") != 0)
			return -EINVAL;
		if (!hash_algo)
			return -EINVAL;
		if (strcmp(hash_algo, "streebog256") != 0 &&
		    strcmp(hash_algo, "streebog512") != 0)
			return -EINVAL;
	} else if (strcmp(pkey->pkey_algo, "mldsa44") == 0 ||
		   strcmp(pkey->pkey_algo, "mldsa65") == 0 ||
		   strcmp(pkey->pkey_algo, "mldsa87") == 0) {
		if (strcmp(encoding, "raw") != 0)
			return -EINVAL;
		if (!hash_algo)
			return -EINVAL;
		if (strcmp(hash_algo, "none") != 0 &&
		    strcmp(hash_algo, "sha512") != 0)
			return -EINVAL;
	} else {
		/* Unknown public key algorithm */
		return -ENOPKG;
	}
	if (strscpy(alg_name, pkey->pkey_algo, CRYPTO_MAX_ALG_NAME) < 0)
		return -EINVAL;
	return 0;
}

static u8 *pkey_pack_u32(u8 *dst, u32 val)
{
	memcpy(dst, &val, sizeof(val));
	return dst + sizeof(val);
}

/*
 * Query information about a key.
 */

Annotation

Implementation Notes