]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/ubifs/auth.c
Merge branch 'pm-devfreq'
[linux.git] / fs / ubifs / auth.c
index 38718026ad0b15c26762eeb780b47a8fbb7ff951..d9af2de9084af584e815da014d77614eae145d41 100644 (file)
  */
 
 #include <linux/crypto.h>
+#include <linux/verification.h>
 #include <crypto/hash.h>
 #include <crypto/sha.h>
 #include <crypto/algapi.h>
 #include <keys/user-type.h>
+#include <keys/asymmetric-type.h>
 
 #include "ubifs.h"
 
@@ -198,6 +200,77 @@ int __ubifs_node_check_hash(const struct ubifs_info *c, const void *node,
        return 0;
 }
 
+/**
+ * ubifs_sb_verify_signature - verify the signature of a superblock
+ * @c: UBIFS file-system description object
+ * @sup: The superblock node
+ *
+ * To support offline signed images the superblock can be signed with a
+ * PKCS#7 signature. The signature is placed directly behind the superblock
+ * node in an ubifs_sig_node.
+ *
+ * Returns 0 when the signature can be successfully verified or a negative
+ * error code if not.
+ */
+int ubifs_sb_verify_signature(struct ubifs_info *c,
+                             const struct ubifs_sb_node *sup)
+{
+       int err;
+       struct ubifs_scan_leb *sleb;
+       struct ubifs_scan_node *snod;
+       const struct ubifs_sig_node *signode;
+
+       sleb = ubifs_scan(c, UBIFS_SB_LNUM, UBIFS_SB_NODE_SZ, c->sbuf, 0);
+       if (IS_ERR(sleb)) {
+               err = PTR_ERR(sleb);
+               return err;
+       }
+
+       if (sleb->nodes_cnt == 0) {
+               ubifs_err(c, "Unable to find signature node");
+               err = -EINVAL;
+               goto out_destroy;
+       }
+
+       snod = list_first_entry(&sleb->nodes, struct ubifs_scan_node, list);
+
+       if (snod->type != UBIFS_SIG_NODE) {
+               ubifs_err(c, "Signature node is of wrong type");
+               err = -EINVAL;
+               goto out_destroy;
+       }
+
+       signode = snod->node;
+
+       if (le32_to_cpu(signode->len) > snod->len + sizeof(struct ubifs_sig_node)) {
+               ubifs_err(c, "invalid signature len %d", le32_to_cpu(signode->len));
+               err = -EINVAL;
+               goto out_destroy;
+       }
+
+       if (le32_to_cpu(signode->type) != UBIFS_SIGNATURE_TYPE_PKCS7) {
+               ubifs_err(c, "Signature type %d is not supported\n",
+                         le32_to_cpu(signode->type));
+               err = -EINVAL;
+               goto out_destroy;
+       }
+
+       err = verify_pkcs7_signature(sup, sizeof(struct ubifs_sb_node),
+                                    signode->sig, le32_to_cpu(signode->len),
+                                    NULL, VERIFYING_UNSPECIFIED_SIGNATURE,
+                                    NULL, NULL);
+
+       if (err)
+               ubifs_err(c, "Failed to verify signature");
+       else
+               ubifs_msg(c, "Successfully verified super block signature");
+
+out_destroy:
+       ubifs_scan_destroy(sleb);
+
+       return err;
+}
+
 /**
  * ubifs_init_authentication - initialize UBIFS authentication support
  * @c: UBIFS file-system description object
@@ -227,7 +300,7 @@ int ubifs_init_authentication(struct ubifs_info *c)
        snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)",
                 c->auth_hash_name);
 
-       keyring_key = request_key(&key_type_logon, c->auth_key_name, NULL, NULL);
+       keyring_key = request_key(&key_type_logon, c->auth_key_name, NULL);
 
        if (IS_ERR(keyring_key)) {
                ubifs_err(c, "Failed to request key: %ld",
@@ -478,3 +551,16 @@ int ubifs_hmac_wkm(struct ubifs_info *c, u8 *hmac)
                return err;
        return 0;
 }
+
+/*
+ * ubifs_hmac_zero - test if a HMAC is zero
+ * @c: UBIFS file-system description object
+ * @hmac: the HMAC to test
+ *
+ * This function tests if a HMAC is zero and returns true if it is
+ * and false otherwise.
+ */
+bool ubifs_hmac_zero(struct ubifs_info *c, const u8 *hmac)
+{
+       return !memchr_inv(hmac, 0, c->hmac_desc_len);
+}