Skip to content

Commit

Permalink
Merge tag 'keys-fixes-20171208' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/dhowells/linux-fs into keys-for-linus

Assorted fixes for keyrings, ASN.1, X.509 and PKCS#7.
  • Loading branch information
James Morris committed Dec 9, 2017
2 parents f335195 + 54c1fb3 commit 4ded3be
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 69 deletions.
4 changes: 3 additions & 1 deletion crypto/asymmetric_keys/pkcs7_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,10 @@ struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
}

ret = pkcs7_check_authattrs(ctx->msg);
if (ret < 0)
if (ret < 0) {
msg = ERR_PTR(ret);
goto out;
}

msg = ctx->msg;
ctx->msg = NULL;
Expand Down
2 changes: 1 addition & 1 deletion crypto/asymmetric_keys/pkcs7_trust.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
/* Self-signed certificates form roots of their own, and if we
* don't know them, then we can't accept them.
*/
if (x509->next == x509) {
if (x509->signer == x509) {
kleave(" = -ENOKEY [unknown self-signed]");
return -ENOKEY;
}
Expand Down
9 changes: 3 additions & 6 deletions crypto/asymmetric_keys/pkcs7_verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,8 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;

/* Digest the message [RFC2315 9.3] */
ret = crypto_shash_init(desc);
if (ret < 0)
goto error;
ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len,
sig->digest);
ret = crypto_shash_digest(desc, pkcs7->data, pkcs7->data_len,
sig->digest);
if (ret < 0)
goto error;
pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest);
Expand Down Expand Up @@ -150,7 +147,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
sinfo->index, certix);

if (x509->pub->pkey_algo != sinfo->sig->pkey_algo) {
if (strcmp(x509->pub->pkey_algo, sinfo->sig->pkey_algo) != 0) {
pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
sinfo->index);
continue;
Expand Down
7 changes: 5 additions & 2 deletions crypto/asymmetric_keys/public_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ int public_key_verify_signature(const struct public_key *pkey,
char alg_name_buf[CRYPTO_MAX_ALG_NAME];
void *output;
unsigned int outlen;
int ret = -ENOMEM;
int ret;

pr_devel("==>%s()\n", __func__);

Expand All @@ -99,6 +99,7 @@ int public_key_verify_signature(const struct public_key *pkey,
if (IS_ERR(tfm))
return PTR_ERR(tfm);

ret = -ENOMEM;
req = akcipher_request_alloc(tfm, GFP_KERNEL);
if (!req)
goto error_free_tfm;
Expand Down Expand Up @@ -127,7 +128,7 @@ int public_key_verify_signature(const struct public_key *pkey,
* signature and returns that to us.
*/
ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
if (ret < 0)
if (ret)
goto out_free_output;

/* Do the actual verification step. */
Expand All @@ -142,6 +143,8 @@ int public_key_verify_signature(const struct public_key *pkey,
error_free_tfm:
crypto_free_akcipher(tfm);
pr_devel("<==%s() = %d\n", __func__, ret);
if (WARN_ON_ONCE(ret > 0))
ret = -EINVAL;
return ret;
}
EXPORT_SYMBOL_GPL(public_key_verify_signature);
Expand Down
2 changes: 2 additions & 0 deletions crypto/asymmetric_keys/x509_cert_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,8 @@ int x509_extract_key_data(void *context, size_t hdrlen,
ctx->cert->pub->pkey_algo = "rsa";

/* Discard the BIT STRING metadata */
if (vlen < 1 || *(const u8 *)value != 0)
return -EBADMSG;
ctx->key = value + 1;
ctx->key_size = vlen - 1;
return 0;
Expand Down
8 changes: 2 additions & 6 deletions crypto/asymmetric_keys/x509_public_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,7 @@ int x509_get_sig_params(struct x509_certificate *cert)
desc->tfm = tfm;
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;

ret = crypto_shash_init(desc);
if (ret < 0)
goto error_2;
might_sleep();
ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->digest);
if (ret < 0)
goto error_2;

Expand Down Expand Up @@ -135,7 +131,7 @@ int x509_check_for_self_signed(struct x509_certificate *cert)
}

ret = -EKEYREJECTED;
if (cert->pub->pkey_algo != cert->sig->pkey_algo)
if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0)
goto out;

ret = public_key_verify_signature(cert->pub, cert->sig);
Expand Down
49 changes: 28 additions & 21 deletions lib/asn1_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,42 +313,47 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,

/* Decide how to handle the operation */
switch (op) {
case ASN1_OP_MATCH_ANY_ACT:
case ASN1_OP_MATCH_ANY_ACT_OR_SKIP:
case ASN1_OP_COND_MATCH_ANY_ACT:
case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP:
ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len);
if (ret < 0)
return ret;
goto skip_data;

case ASN1_OP_MATCH_ACT:
case ASN1_OP_MATCH_ACT_OR_SKIP:
case ASN1_OP_COND_MATCH_ACT_OR_SKIP:
ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len);
if (ret < 0)
return ret;
goto skip_data;

case ASN1_OP_MATCH:
case ASN1_OP_MATCH_OR_SKIP:
case ASN1_OP_MATCH_ACT:
case ASN1_OP_MATCH_ACT_OR_SKIP:
case ASN1_OP_MATCH_ANY:
case ASN1_OP_MATCH_ANY_OR_SKIP:
case ASN1_OP_MATCH_ANY_ACT:
case ASN1_OP_MATCH_ANY_ACT_OR_SKIP:
case ASN1_OP_COND_MATCH_OR_SKIP:
case ASN1_OP_COND_MATCH_ACT_OR_SKIP:
case ASN1_OP_COND_MATCH_ANY:
case ASN1_OP_COND_MATCH_ANY_OR_SKIP:
skip_data:
case ASN1_OP_COND_MATCH_ANY_ACT:
case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP:

if (!(flags & FLAG_CONS)) {
if (flags & FLAG_INDEFINITE_LENGTH) {
size_t tmp = dp;

ret = asn1_find_indefinite_length(
data, datalen, &dp, &len, &errmsg);
data, datalen, &tmp, &len, &errmsg);
if (ret < 0)
goto error;
} else {
dp += len;
}
pr_debug("- LEAF: %zu\n", len);
}

if (op & ASN1_OP_MATCH__ACT) {
unsigned char act;

if (op & ASN1_OP_MATCH__ANY)
act = machine[pc + 1];
else
act = machine[pc + 2];
ret = actions[act](context, hdr, tag, data + dp, len);
if (ret < 0)
return ret;
}

if (!(flags & FLAG_CONS))
dp += len;
pc += asn1_op_lengths[op];
goto next_op;

Expand Down Expand Up @@ -434,6 +439,8 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
else
act = machine[pc + 1];
ret = actions[act](context, hdr, 0, data + tdp, len);
if (ret < 0)
return ret;
}
pc += asn1_op_lengths[op];
goto next_op;
Expand Down
16 changes: 10 additions & 6 deletions lib/oid_registry.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,14 @@ int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize)
int count;

if (v >= end)
return -EBADMSG;
goto bad;

n = *v++;
ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40);
if (count >= bufsize)
return -ENOBUFS;
buffer += count;
bufsize -= count;
if (bufsize == 0)
return -ENOBUFS;

while (v < end) {
num = 0;
Expand All @@ -134,20 +134,24 @@ int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize)
num = n & 0x7f;
do {
if (v >= end)
return -EBADMSG;
goto bad;
n = *v++;
num <<= 7;
num |= n & 0x7f;
} while (n & 0x80);
}
ret += count = snprintf(buffer, bufsize, ".%lu", num);
buffer += count;
if (bufsize <= count)
if (count >= bufsize)
return -ENOBUFS;
buffer += count;
bufsize -= count;
}

return ret;

bad:
snprintf(buffer, bufsize, "(bad)");
return -EBADMSG;
}
EXPORT_SYMBOL_GPL(sprint_oid);

Expand Down
1 change: 0 additions & 1 deletion security/keys/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,6 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,

key_check(keyring);

key_ref = ERR_PTR(-EPERM);
if (!(flags & KEY_ALLOC_BYPASS_RESTRICTION))
restrict_link = keyring->restrict_link;

Expand Down
24 changes: 10 additions & 14 deletions security/keys/keyctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1588,17 +1588,15 @@ long keyctl_session_to_parent(void)
* The caller must have Setattr permission to change keyring restrictions.
*
* The requested type name may be a NULL pointer to reject all attempts
* to link to the keyring. If _type is non-NULL, _restriction can be
* NULL or a pointer to a string describing the restriction. If _type is
* NULL, _restriction must also be NULL.
* to link to the keyring. In this case, _restriction must also be NULL.
* Otherwise, both _type and _restriction must be non-NULL.
*
* Returns 0 if successful.
*/
long keyctl_restrict_keyring(key_serial_t id, const char __user *_type,
const char __user *_restriction)
{
key_ref_t key_ref;
bool link_reject = !_type;
char type[32];
char *restriction = NULL;
long ret;
Expand All @@ -1607,31 +1605,29 @@ long keyctl_restrict_keyring(key_serial_t id, const char __user *_type,
if (IS_ERR(key_ref))
return PTR_ERR(key_ref);

ret = -EINVAL;
if (_type) {
ret = key_get_type_from_user(type, _type, sizeof(type));
if (ret < 0)
if (!_restriction)
goto error;
}

if (_restriction) {
if (!_type) {
ret = -EINVAL;
ret = key_get_type_from_user(type, _type, sizeof(type));
if (ret < 0)
goto error;
}

restriction = strndup_user(_restriction, PAGE_SIZE);
if (IS_ERR(restriction)) {
ret = PTR_ERR(restriction);
goto error;
}
} else {
if (_restriction)
goto error;
}

ret = keyring_restrict(key_ref, link_reject ? NULL : type, restriction);
ret = keyring_restrict(key_ref, _type ? type : NULL, restriction);
kfree(restriction);

error:
key_ref_put(key_ref);

return ret;
}

Expand Down
Loading

0 comments on commit 4ded3be

Please sign in to comment.