if (!params || (!buffer && buflen)) {
ret = -EINVAL; goto out1;
} if (copy_from_user(&pcopy, params, sizeof(pcopy)) != 0) {
ret = -EFAULT; goto out1;
}
if (kdfcopy) { char *hashname;
if (memchr_inv(kdfcopy->__spare, 0, sizeof(kdfcopy->__spare))) {
ret = -EINVAL; goto out1;
}
if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN ||
kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) {
ret = -EMSGSIZE; goto out1;
}
/* get KDF name string */
hashname = strndup_user(kdfcopy->hashname, CRYPTO_MAX_ALG_NAME); if (IS_ERR(hashname)) {
ret = PTR_ERR(hashname); goto out1;
}
/* allocate KDF from the kernel crypto API */
ret = kdf_alloc(&hash, hashname);
kfree(hashname); if (ret) goto out1;
}
memset(&dh_inputs, 0, sizeof(dh_inputs));
dlen = dh_data_from_key(pcopy.prime, &dh_inputs.p); if (dlen < 0) {
ret = dlen; goto out1;
}
dh_inputs.p_size = dlen;
dlen = dh_data_from_key(pcopy.base, &dh_inputs.g); if (dlen < 0) {
ret = dlen; goto out2;
}
dh_inputs.g_size = dlen;
dlen = dh_data_from_key(pcopy.private, &dh_inputs.key); if (dlen < 0) {
ret = dlen; goto out2;
}
dh_inputs.key_size = dlen;
secretlen = crypto_dh_key_len(&dh_inputs);
secret = kmalloc(secretlen, GFP_KERNEL); if (!secret) {
ret = -ENOMEM; goto out2;
}
ret = crypto_dh_encode_key(secret, secretlen, &dh_inputs); if (ret) goto out3;
tfm = crypto_alloc_kpp("dh", 0, 0); if (IS_ERR(tfm)) {
ret = PTR_ERR(tfm); goto out3;
}
ret = crypto_kpp_set_secret(tfm, secret, secretlen); if (ret) goto out4;
outlen = crypto_kpp_maxsize(tfm);
if (!kdfcopy) { /* * When not using a KDF, buflen 0 is used to read the * required buffer length
*/ if (buflen == 0) {
ret = outlen; goto out4;
} elseif (outlen > buflen) {
ret = -EOVERFLOW; goto out4;
}
}
outbuf = kzalloc(kdfcopy ? (outlen + kdfcopy->otherinfolen) : outlen,
GFP_KERNEL); if (!outbuf) {
ret = -ENOMEM; goto out4;
}
sg_init_one(&outsg, outbuf, outlen);
req = kpp_request_alloc(tfm, GFP_KERNEL); if (!req) {
ret = -ENOMEM; goto out5;
}
/* * For DH, generate_public_key and generate_shared_secret are * the same calculation
*/
ret = crypto_kpp_generate_public_key(req);
ret = crypto_wait_req(ret, &compl); if (ret) goto out6;
if (kdfcopy) { /* * Concatenate SP800-56A otherinfo past DH shared secret -- the * input to the KDF is (DH shared secret || otherinfo)
*/ if (copy_from_user(outbuf + req->dst_len, kdfcopy->otherinfo,
kdfcopy->otherinfolen) != 0) {
ret = -EFAULT; goto out6;
}
ret = keyctl_dh_compute_kdf(hash, buffer, buflen, outbuf,
req->dst_len + kdfcopy->otherinfolen);
} elseif (copy_to_user(buffer, outbuf, req->dst_len) == 0) {
ret = req->dst_len;
} else {
ret = -EFAULT;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.