Assorted fixes for keyrings, ASN.1, X.509 and PKCS#7.
Unified · Split
| @@ -148,8 +148,10 @@ struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen) · 147 unmodified lines | ||
| 148 | 148 | } |
| 149 | 149 | |
| 150 | 150 | ret = pkcs7_check_authattrs(ctx->msg); |
| 151 | − if (ret < 0) | |
| 151 | + if (ret < 0) { | |
| 152 | + msg = ERR_PTR(ret); | |
| 152 | 153 | goto out; |
| 154 | + } | |
| 153 | 155 | |
| 154 | 156 | msg = ctx->msg; |
| 155 | 157 | ctx->msg = NULL; |
| @@ -69,7 +69,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, · 68 unmodified lines | ||
| 69 | 69 | /* Self-signed certificates form roots of their own, and if we |
| 70 | 70 | * don't know them, then we can't accept them. |
| 71 | 71 | */ |
| 72 | − if (x509->next == x509) { | |
| 72 | + if (x509->signer == x509) { | |
| 73 | 73 | kleave(" = -ENOKEY [unknown self-signed]"); |
| 74 | 74 | return -ENOKEY; |
| 75 | 75 | } |
| @@ -59,11 +59,8 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, · 58 unmodified lines | ||
| 59 | 59 | desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; |
| 60 | 60 | |
| 61 | 61 | /* Digest the message [RFC2315 9.3] */ |
| 62 | − ret = crypto_shash_init(desc); | |
| 63 | − if (ret < 0) | |
| 64 | − goto error; | |
| 65 | − ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len, | |
| 66 | − sig->digest); | |
| 62 | + ret = crypto_shash_digest(desc, pkcs7->data, pkcs7->data_len, | |
| 63 | + sig->digest); | |
| 67 | 64 | if (ret < 0) |
| 68 | 65 | goto error; |
| 69 | 66 | pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest); |
| @@ -150,7 +147,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, · 80 unmodified lines | ||
| 150 | 147 | pr_devel("Sig %u: Found cert serial match X.509[%u]\n", |
| 151 | 148 | sinfo->index, certix); |
| 152 | 149 | |
| 153 | − if (x509->pub->pkey_algo != sinfo->sig->pkey_algo) { | |
| 150 | + if (strcmp(x509->pub->pkey_algo, sinfo->sig->pkey_algo) != 0) { | |
| 154 | 151 | pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n", |
| 155 | 152 | sinfo->index); |
| 156 | 153 | continue; |
| @@ -73,7 +73,7 @@ int public_key_verify_signature(const struct public_key *pkey, · 72 unmodified lines | ||
| 73 | 73 | char alg_name_buf[CRYPTO_MAX_ALG_NAME]; |
| 74 | 74 | void *output; |
| 75 | 75 | unsigned int outlen; |
| 76 | − int ret = -ENOMEM; | |
| 76 | + int ret; | |
| 77 | 77 | |
| 78 | 78 | pr_devel("==>%s()\n", __func__); |
| 79 | 79 | |
| @@ -99,6 +99,7 @@ int public_key_verify_signature(const struct public_key *pkey, · 19 unmodified lines | ||
| 99 | 99 | if (IS_ERR(tfm)) |
| 100 | 100 | return PTR_ERR(tfm); |
| 101 | 101 | |
| 102 | + ret = -ENOMEM; | |
| 102 | 103 | req = akcipher_request_alloc(tfm, GFP_KERNEL); |
| 103 | 104 | if (!req) |
| 104 | 105 | goto error_free_tfm; |
| @@ -127,7 +128,7 @@ int public_key_verify_signature(const struct public_key *pkey, · 22 unmodified lines | ||
| 127 | 128 | * signature and returns that to us. |
| 128 | 129 | */ |
| 129 | 130 | ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait); |
| 130 | − if (ret < 0) | |
| 131 | + if (ret) | |
| 131 | 132 | goto out_free_output; |
| 132 | 133 | |
| 133 | 134 | /* Do the actual verification step. */ |
| @@ -142,6 +143,8 @@ error_free_req: · 8 unmodified lines | ||
| 142 | 143 | error_free_tfm: |
| 143 | 144 | crypto_free_akcipher(tfm); |
| 144 | 145 | pr_devel("<==%s() = %d\n", __func__, ret); |
| 146 | + if (WARN_ON_ONCE(ret > 0)) | |
| 147 | + ret = -EINVAL; | |
| 145 | 148 | return ret; |
| 146 | 149 | } |
| 147 | 150 | EXPORT_SYMBOL_GPL(public_key_verify_signature); |
| @@ -409,6 +409,8 @@ int x509_extract_key_data(void *context, size_t hdrlen, · 408 unmodified lines | ||
| 409 | 409 | ctx->cert->pub->pkey_algo = "rsa"; |
| 410 | 410 | |
| 411 | 411 | /* Discard the BIT STRING metadata */ |
| 412 | + if (vlen < 1 || *(const u8 *)value != 0) | |
| 413 | + return -EBADMSG; | |
| 412 | 414 | ctx->key = value + 1; |
| 413 | 415 | ctx->key_size = vlen - 1; |
| 414 | 416 | return 0; |
| @@ -79,11 +79,7 @@ int x509_get_sig_params(struct x509_certificate *cert) · 78 unmodified lines | ||
| 79 | 79 | desc->tfm = tfm; |
| 80 | 80 | desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; |
| 81 | 81 | |
| 82 | − ret = crypto_shash_init(desc); | |
| 83 | − if (ret < 0) | |
| 84 | − goto error_2; | |
| 85 | − might_sleep(); | |
| 86 | − ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); | |
| 82 | + ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->digest); | |
| 87 | 83 | if (ret < 0) |
| 88 | 84 | goto error_2; |
| 89 | 85 | |
| @@ -135,7 +131,7 @@ int x509_check_for_self_signed(struct x509_certificate *cert) · 45 unmodified lines | ||
| 135 | 131 | } |
| 136 | 132 | |
| 137 | 133 | ret = -EKEYREJECTED; |
| 138 | − if (cert->pub->pkey_algo != cert->sig->pkey_algo) | |
| 134 | + if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0) | |
| 139 | 135 | goto out; |
| 140 | 136 | |
| 141 | 137 | ret = public_key_verify_signature(cert->pub, cert->sig); |
| @@ -313,42 +313,47 @@ next_op: · 312 unmodified lines | ||
| 313 | 313 | |
| 314 | 314 | /* Decide how to handle the operation */ |
| 315 | 315 | switch (op) { |
| 316 | − case ASN1_OP_MATCH_ANY_ACT: | |
| 317 | − case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: | |
| 318 | − case ASN1_OP_COND_MATCH_ANY_ACT: | |
| 319 | − case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: | |
| 320 | − ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); | |
| 321 | − if (ret < 0) | |
| 322 | − return ret; | |
| 323 | − goto skip_data; | |
| 324 | − | |
| 325 | − case ASN1_OP_MATCH_ACT: | |
| 326 | − case ASN1_OP_MATCH_ACT_OR_SKIP: | |
| 327 | − case ASN1_OP_COND_MATCH_ACT_OR_SKIP: | |
| 328 | − ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); | |
| 329 | − if (ret < 0) | |
| 330 | − return ret; | |
| 331 | − goto skip_data; | |
| 332 | − | |
| 333 | 316 | case ASN1_OP_MATCH: |
| 334 | 317 | case ASN1_OP_MATCH_OR_SKIP: |
| 318 | + case ASN1_OP_MATCH_ACT: | |
| 319 | + case ASN1_OP_MATCH_ACT_OR_SKIP: | |
| 335 | 320 | case ASN1_OP_MATCH_ANY: |
| 336 | 321 | case ASN1_OP_MATCH_ANY_OR_SKIP: |
| 322 | + case ASN1_OP_MATCH_ANY_ACT: | |
| 323 | + case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: | |
| 337 | 324 | case ASN1_OP_COND_MATCH_OR_SKIP: |
| 325 | + case ASN1_OP_COND_MATCH_ACT_OR_SKIP: | |
| 338 | 326 | case ASN1_OP_COND_MATCH_ANY: |
| 339 | 327 | case ASN1_OP_COND_MATCH_ANY_OR_SKIP: |
| 340 | − skip_data: | |
| 328 | + case ASN1_OP_COND_MATCH_ANY_ACT: | |
| 329 | + case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: | |
| 330 | + | |
| 341 | 331 | if (!(flags & FLAG_CONS)) { |
| 342 | 332 | if (flags & FLAG_INDEFINITE_LENGTH) { |
| 333 | + size_t tmp = dp; | |
| 334 | + | |
| 343 | 335 | ret = asn1_find_indefinite_length( |
| 344 | − data, datalen, &dp, &len, &errmsg); | |
| 336 | + data, datalen, &tmp, &len, &errmsg); | |
| 345 | 337 | if (ret < 0) |
| 346 | 338 | goto error; |
| 347 | − } else { | |
| 348 | − dp += len; | |
| 349 | 339 | } |
| 350 | 340 | pr_debug("- LEAF: %zu\n", len); |
| 351 | 341 | } |
| 342 | + | |
| 343 | + if (op & ASN1_OP_MATCH__ACT) { | |
| 344 | + unsigned char act; | |
| 345 | + | |
| 346 | + if (op & ASN1_OP_MATCH__ANY) | |
| 347 | + act = machine[pc + 1]; | |
| 348 | + else | |
| 349 | + act = machine[pc + 2]; | |
| 350 | + ret = actions[act](context, hdr, tag, data + dp, len); | |
| 351 | + if (ret < 0) | |
| 352 | + return ret; | |
| 353 | + } | |
| 354 | + | |
| 355 | + if (!(flags & FLAG_CONS)) | |
| 356 | + dp += len; | |
| 352 | 357 | pc += asn1_op_lengths[op]; |
| 353 | 358 | goto next_op; |
| 354 | 359 | |
| @@ -434,6 +439,8 @@ next_op: · 79 unmodified lines | ||
| 434 | 439 | else |
| 435 | 440 | act = machine[pc + 1]; |
| 436 | 441 | ret = actions[act](context, hdr, 0, data + tdp, len); |
| 442 | + if (ret < 0) | |
| 443 | + return ret; | |
| 437 | 444 | } |
| 438 | 445 | pc += asn1_op_lengths[op]; |
| 439 | 446 | goto next_op; |
| @@ -116,14 +116,14 @@ int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) · 115 unmodified lines | ||
| 116 | 116 | int count; |
| 117 | 117 | |
| 118 | 118 | if (v >= end) |
| 119 | − return -EBADMSG; | |
| 119 | + goto bad; | |
| 120 | 120 | |
| 121 | 121 | n = *v++; |
| 122 | 122 | ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); |
| 123 | + if (count >= bufsize) | |
| 124 | + return -ENOBUFS; | |
| 123 | 125 | buffer += count; |
| 124 | 126 | bufsize -= count; |
| 125 | − if (bufsize == 0) | |
| 126 | − return -ENOBUFS; | |
| 127 | 127 | |
| 128 | 128 | while (v < end) { |
| 129 | 129 | num = 0; |
| @@ -134,20 +134,24 @@ int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) · 4 unmodified lines | ||
| 134 | 134 | num = n & 0x7f; |
| 135 | 135 | do { |
| 136 | 136 | if (v >= end) |
| 137 | − return -EBADMSG; | |
| 137 | + goto bad; | |
| 138 | 138 | n = *v++; |
| 139 | 139 | num <<= 7; |
| 140 | 140 | num |= n & 0x7f; |
| 141 | 141 | } while (n & 0x80); |
| 142 | 142 | } |
| 143 | 143 | ret += count = snprintf(buffer, bufsize, ".%lu", num); |
| 144 | − buffer += count; | |
| 145 | − if (bufsize <= count) | |
| 144 | + if (count >= bufsize) | |
| 146 | 145 | return -ENOBUFS; |
| 146 | + buffer += count; | |
| 147 | 147 | bufsize -= count; |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | 150 | return ret; |
| 151 | + | |
| 152 | +bad: | |
| 153 | + snprintf(buffer, bufsize, "(bad)"); | |
| 154 | + return -EBADMSG; | |
| 151 | 155 | } |
| 152 | 156 | EXPORT_SYMBOL_GPL(sprint_oid); |
| 153 | 157 | |
| @@ -833,7 +833,6 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, · 832 unmodified lines | ||
| 833 | 833 | |
| 834 | 834 | key_check(keyring); |
| 835 | 835 | |
| 836 | − key_ref = ERR_PTR(-EPERM); | |
| 837 | 836 | if (!(flags & KEY_ALLOC_BYPASS_RESTRICTION)) |
| 838 | 837 | restrict_link = keyring->restrict_link; |
| 839 | 838 | |
| @@ -1588,9 +1588,8 @@ error_keyring: · 1587 unmodified lines | ||
| 1588 | 1588 | * The caller must have Setattr permission to change keyring restrictions. |
| 1589 | 1589 | * |
| 1590 | 1590 | * The requested type name may be a NULL pointer to reject all attempts |
| 1591 | − * to link to the keyring. If _type is non-NULL, _restriction can be | |
| 1592 | − * NULL or a pointer to a string describing the restriction. If _type is | |
| 1593 | − * NULL, _restriction must also be NULL. | |
| 1591 | + * to link to the keyring. In this case, _restriction must also be NULL. | |
| 1592 | + * Otherwise, both _type and _restriction must be non-NULL. | |
| 1594 | 1593 | * |
| 1595 | 1594 | * Returns 0 if successful. |
| 1596 | 1595 | */ |
| @@ -1598,7 +1597,6 @@ long keyctl_restrict_keyring(key_serial_t id, const char __user *_type, · 1 unmodified line | ||
| 1598 | 1597 | const char __user *_restriction) |
| 1599 | 1598 | { |
| 1600 | 1599 | key_ref_t key_ref; |
| 1601 | − bool link_reject = !_type; | |
| 1602 | 1600 | char type[32]; |
| 1603 | 1601 | char *restriction = NULL; |
| 1604 | 1602 | long ret; |
| @@ -1607,31 +1605,29 @@ long keyctl_restrict_keyring(key_serial_t id, const char __user *_type, · 2 unmodified lines | ||
| 1607 | 1605 | if (IS_ERR(key_ref)) |
| 1608 | 1606 | return PTR_ERR(key_ref); |
| 1609 | 1607 | |
| 1608 | + ret = -EINVAL; | |
| 1610 | 1609 | if (_type) { |
| 1611 | − ret = key_get_type_from_user(type, _type, sizeof(type)); | |
| 1612 | − if (ret < 0) | |
| 1610 | + if (!_restriction) | |
| 1613 | 1611 | goto error; |
| 1614 | − } | |
| 1615 | 1612 | |
| 1616 | − if (_restriction) { | |
| 1617 | − if (!_type) { | |
| 1618 | − ret = -EINVAL; | |
| 1613 | + ret = key_get_type_from_user(type, _type, sizeof(type)); | |
| 1614 | + if (ret < 0) | |
| 1619 | 1615 | goto error; |
| 1620 | − } | |
| 1621 | 1616 | |
| 1622 | 1617 | restriction = strndup_user(_restriction, PAGE_SIZE); |
| 1623 | 1618 | if (IS_ERR(restriction)) { |
| 1624 | 1619 | ret = PTR_ERR(restriction); |
| 1625 | 1620 | goto error; |
| 1626 | 1621 | } |
| 1622 | + } else { | |
| 1623 | + if (_restriction) | |
| 1624 | + goto error; | |
| 1627 | 1625 | } |
| 1628 | 1626 | |
| 1629 | − ret = keyring_restrict(key_ref, link_reject ? NULL : type, restriction); | |
| 1627 | + ret = keyring_restrict(key_ref, _type ? type : NULL, restriction); | |
| 1630 | 1628 | kfree(restriction); |
| 1631 | − | |
| 1632 | 1629 | error: |
| 1633 | 1630 | key_ref_put(key_ref); |
| 1634 | − | |
| 1635 | 1631 | return ret; |
| 1636 | 1632 | } |
| 1637 | 1633 | |
| @@ -251,11 +251,12 @@ static int construct_key(struct key *key, const void *callout_info, · 250 unmodified lines | ||
| 251 | 251 | * The keyring selected is returned with an extra reference upon it which the |
| 252 | 252 | * caller must release. |
| 253 | 253 | */ |
| 254 | −static void construct_get_dest_keyring(struct key **_dest_keyring) | |
| 254 | +static int construct_get_dest_keyring(struct key **_dest_keyring) | |
| 255 | 255 | { |
| 256 | 256 | struct request_key_auth *rka; |
| 257 | 257 | const struct cred *cred = current_cred(); |
| 258 | 258 | struct key *dest_keyring = *_dest_keyring, *authkey; |
| 259 | + int ret; | |
| 259 | 260 | |
| 260 | 261 | kenter("%p", dest_keyring); |
| 261 | 262 | |
| @@ -264,6 +265,8 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) · 2 unmodified lines | ||
| 264 | 265 | /* the caller supplied one */ |
| 265 | 266 | key_get(dest_keyring); |
| 266 | 267 | } else { |
| 268 | + bool do_perm_check = true; | |
| 269 | + | |
| 267 | 270 | /* use a default keyring; falling through the cases until we |
| 268 | 271 | * find one that we actually have */ |
| 269 | 272 | switch (cred->jit_keyring) { |
| @@ -278,8 +281,10 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) · 8 unmodified lines | ||
| 278 | 281 | dest_keyring = |
| 279 | 282 | key_get(rka->dest_keyring); |
| 280 | 283 | up_read(&authkey->sem); |
| 281 | − if (dest_keyring) | |
| 284 | + if (dest_keyring) { | |
| 285 | + do_perm_check = false; | |
| 282 | 286 | break; |
| 287 | + } | |
| 283 | 288 | } |
| 284 | 289 | |
| 285 | 290 | case KEY_REQKEY_DEFL_THREAD_KEYRING: |
| @@ -314,11 +319,29 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) · 28 unmodified lines | ||
| 314 | 319 | default: |
| 315 | 320 | BUG(); |
| 316 | 321 | } |
| 322 | + | |
| 323 | + /* | |
| 324 | + * Require Write permission on the keyring. This is essential | |
| 325 | + * because the default keyring may be the session keyring, and | |
| 326 | + * joining a keyring only requires Search permission. | |
| 327 | + * | |
| 328 | + * However, this check is skipped for the "requestor keyring" so | |
| 329 | + * that /sbin/request-key can itself use request_key() to add | |
| 330 | + * keys to the original requestor's destination keyring. | |
| 331 | + */ | |
| 332 | + if (dest_keyring && do_perm_check) { | |
| 333 | + ret = key_permission(make_key_ref(dest_keyring, 1), | |
| 334 | + KEY_NEED_WRITE); | |
| 335 | + if (ret) { | |
| 336 | + key_put(dest_keyring); | |
| 337 | + return ret; | |
| 338 | + } | |
| 339 | + } | |
| 317 | 340 | } |
| 318 | 341 | |
| 319 | 342 | *_dest_keyring = dest_keyring; |
| 320 | 343 | kleave(" [dk %d]", key_serial(dest_keyring)); |
| 321 | − return; | |
| 344 | + return 0; | |
| 322 | 345 | } |
| 323 | 346 | |
| 324 | 347 | /* |
| @@ -444,11 +467,15 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx, · 119 unmodified lines | ||
| 444 | 467 | if (ctx->index_key.type == &key_type_keyring) |
| 445 | 468 | return ERR_PTR(-EPERM); |
| 446 | 469 | |
| 447 | − user = key_user_lookup(current_fsuid()); | |
| 448 | − if (!user) | |
| 449 | − return ERR_PTR(-ENOMEM); | |
| 470 | + ret = construct_get_dest_keyring(&dest_keyring); | |
| 471 | + if (ret) | |
| 472 | + goto error; | |
| 450 | 473 | |
| 451 | − construct_get_dest_keyring(&dest_keyring); | |
| 474 | + user = key_user_lookup(current_fsuid()); | |
| 475 | + if (!user) { | |
| 476 | + ret = -ENOMEM; | |
| 477 | + goto error_put_dest_keyring; | |
| 478 | + } | |
| 452 | 479 | |
| 453 | 480 | ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key); |
| 454 | 481 | key_user_put(user); |
| @@ -463,7 +490,7 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx, · 8 unmodified lines | ||
| 463 | 490 | } else if (ret == -EINPROGRESS) { |
| 464 | 491 | ret = 0; |
| 465 | 492 | } else { |
| 466 | − goto couldnt_alloc_key; | |
| 493 | + goto error_put_dest_keyring; | |
| 467 | 494 | } |
| 468 | 495 | |
| 469 | 496 | key_put(dest_keyring); |
| @@ -473,8 +500,9 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx, · 3 unmodified lines | ||
| 473 | 500 | construction_failed: |
| 474 | 501 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); |
| 475 | 502 | key_put(key); |
| 476 | −couldnt_alloc_key: | |
| 503 | +error_put_dest_keyring: | |
| 477 | 504 | key_put(dest_keyring); |
| 505 | +error: | |
| 478 | 506 | kleave(" = %d", ret); |
| 479 | 507 | return ERR_PTR(ret); |
| 480 | 508 | } |
| @@ -546,9 +574,7 @@ struct key *request_key_and_link(struct key_type *type, · 65 unmodified lines | ||
| 546 | 574 | if (!IS_ERR(key_ref)) { |
| 547 | 575 | key = key_ref_to_ptr(key_ref); |
| 548 | 576 | if (dest_keyring) { |
| 549 | − construct_get_dest_keyring(&dest_keyring); | |
| 550 | 577 | ret = key_link(dest_keyring, key); |
| 551 | − key_put(dest_keyring); | |
| 552 | 578 | if (ret < 0) { |
| 553 | 579 | key_put(key); |
| 554 | 580 | key = ERR_PTR(ret); |