These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / crypto / asymmetric_keys / x509_public_key.c
index 24f17e6..2a44b37 100644 (file)
@@ -65,23 +65,37 @@ __setup("ca_keys=", ca_keys_setup);
 /**
  * x509_request_asymmetric_key - Request a key by X.509 certificate params.
  * @keyring: The keys to search.
- * @kid: The key ID.
+ * @id: The issuer & serialNumber to look for or NULL.
+ * @skid: The subjectKeyIdentifier to look for or NULL.
  * @partial: Use partial match if true, exact if false.
  *
- * Find a key in the given keyring by subject name and key ID.  These might,
- * for instance, be the issuer name and the authority key ID of an X.509
- * certificate that needs to be verified.
+ * Find a key in the given keyring by identifier.  The preferred identifier is
+ * the issuer + serialNumber and the fallback identifier is the
+ * subjectKeyIdentifier.  If both are given, the lookup is by the former, but
+ * the latter must also match.
  */
 struct key *x509_request_asymmetric_key(struct key *keyring,
-                                       const struct asymmetric_key_id *kid,
+                                       const struct asymmetric_key_id *id,
+                                       const struct asymmetric_key_id *skid,
                                        bool partial)
 {
-       key_ref_t key;
-       char *id, *p;
-
+       struct key *key;
+       key_ref_t ref;
+       const char *lookup;
+       char *req, *p;
+       int len;
+
+       if (id) {
+               lookup = id->data;
+               len = id->len;
+       } else {
+               lookup = skid->data;
+               len = skid->len;
+       }
+       
        /* Construct an identifier "id:<keyid>". */
-       p = id = kmalloc(2 + 1 + kid->len * 2 + 1, GFP_KERNEL);
-       if (!id)
+       p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL);
+       if (!req)
                return ERR_PTR(-ENOMEM);
 
        if (partial) {
@@ -92,32 +106,48 @@ struct key *x509_request_asymmetric_key(struct key *keyring,
                *p++ = 'x';
        }
        *p++ = ':';
-       p = bin2hex(p, kid->data, kid->len);
+       p = bin2hex(p, lookup, len);
        *p = 0;
 
-       pr_debug("Look up: \"%s\"\n", id);
+       pr_debug("Look up: \"%s\"\n", req);
 
-       key = keyring_search(make_key_ref(keyring, 1),
-                            &key_type_asymmetric, id);
-       if (IS_ERR(key))
-               pr_debug("Request for key '%s' err %ld\n", id, PTR_ERR(key));
-       kfree(id);
+       ref = keyring_search(make_key_ref(keyring, 1),
+                            &key_type_asymmetric, req);
+       if (IS_ERR(ref))
+               pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref));
+       kfree(req);
 
-       if (IS_ERR(key)) {
-               switch (PTR_ERR(key)) {
+       if (IS_ERR(ref)) {
+               switch (PTR_ERR(ref)) {
                        /* Hide some search errors */
                case -EACCES:
                case -ENOTDIR:
                case -EAGAIN:
                        return ERR_PTR(-ENOKEY);
                default:
-                       return ERR_CAST(key);
+                       return ERR_CAST(ref);
                }
        }
 
-       pr_devel("<==%s() = 0 [%x]\n", __func__,
-                key_serial(key_ref_to_ptr(key)));
-       return key_ref_to_ptr(key);
+       key = key_ref_to_ptr(ref);
+       if (id && skid) {
+               const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+               if (!kids->id[1]) {
+                       pr_debug("issuer+serial match, but expected SKID missing\n");
+                       goto reject;
+               }
+               if (!asymmetric_key_id_same(skid, kids->id[1])) {
+                       pr_debug("issuer+serial match, but SKID does not\n");
+                       goto reject;
+               }
+       }
+       
+       pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key));
+       return key;
+
+reject:
+       key_put(key);
+       return ERR_PTR(-EKEYREJECTED);
 }
 EXPORT_SYMBOL_GPL(x509_request_asymmetric_key);
 
@@ -164,14 +194,15 @@ int x509_get_sig_params(struct x509_certificate *cert)
         * digest storage space.
         */
        ret = -ENOMEM;
-       digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
+       digest = kzalloc(ALIGN(digest_size, __alignof__(*desc)) + desc_size,
+                        GFP_KERNEL);
        if (!digest)
                goto error;
 
        cert->sig.digest = digest;
        cert->sig.digest_size = digest_size;
 
-       desc = digest + digest_size;
+       desc = PTR_ALIGN(digest + digest_size, __alignof__(*desc));
        desc->tfm = tfm;
        desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
 
@@ -227,15 +258,17 @@ static int x509_validate_trust(struct x509_certificate *cert,
        if (!trust_keyring)
                return -EOPNOTSUPP;
 
-       if (ca_keyid && !asymmetric_key_id_partial(cert->authority, ca_keyid))
+       if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid))
                return -EPERM;
 
-       key = x509_request_asymmetric_key(trust_keyring, cert->authority,
+       key = x509_request_asymmetric_key(trust_keyring,
+                                         cert->akid_id, cert->akid_skid,
                                          false);
        if (!IS_ERR(key))  {
                if (!use_builtin_keys
                    || test_bit(KEY_FLAG_BUILTIN, &key->flags))
-                       ret = x509_check_signature(key->payload.data, cert);
+                       ret = x509_check_signature(key->payload.data[asym_crypto],
+                                                  cert);
                key_put(key);
        }
        return ret;
@@ -271,14 +304,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
        }
 
        pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]);
-       pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n",
-                cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1,
-                cert->valid_from.tm_mday, cert->valid_from.tm_hour,
-                cert->valid_from.tm_min,  cert->valid_from.tm_sec);
-       pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n",
-                cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1,
-                cert->valid_to.tm_mday, cert->valid_to.tm_hour,
-                cert->valid_to.tm_min,  cert->valid_to.tm_sec);
+       pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
        pr_devel("Cert Signature: %s + %s\n",
                 pkey_algo_name[cert->sig.pkey_algo],
                 hash_algo_name[cert->sig.pkey_hash_algo]);
@@ -287,8 +313,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
        cert->pub->id_type = PKEY_ID_X509;
 
        /* Check the signature on the key if it appears to be self-signed */
-       if (!cert->authority ||
-           asymmetric_key_id_same(cert->skid, cert->authority)) {
+       if ((!cert->akid_skid && !cert->akid_id) ||
+           asymmetric_key_id_same(cert->skid, cert->akid_skid) ||
+           asymmetric_key_id_same(cert->id, cert->akid_id)) {
                ret = x509_check_signature(cert->pub, cert); /* self-signed */
                if (ret < 0)
                        goto error_free_cert;
@@ -307,10 +334,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
                srlen = cert->raw_serial_size;
                q = cert->raw_serial;
        }
-       if (srlen > 1 && *q == 0) {
-               srlen--;
-               q++;
-       }
 
        ret = -ENOMEM;
        desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL);
@@ -331,9 +354,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
 
        /* We're pinning the module by being linked against it */
        __module_get(public_key_subtype.owner);
-       prep->type_data[0] = &public_key_subtype;
-       prep->type_data[1] = kids;
-       prep->payload[0] = cert->pub;
+       prep->payload.data[asym_subtype] = &public_key_subtype;
+       prep->payload.data[asym_key_ids] = kids;
+       prep->payload.data[asym_crypto] = cert->pub;
        prep->description = desc;
        prep->quotalen = 100;