crypto: stm32/cryp - reorder hw initialization
authorNicolas Toromanoff <nicolas.toromanoff@foss.st.com>
Tue, 30 Nov 2021 07:55:01 +0000 (08:55 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Sat, 11 Dec 2021 05:48:06 +0000 (16:48 +1100)
The CRYP IP checks the written key depending of the configuration, it's
safer to write the whole configuration to hardware then the key to avoid
unexpected key rejection.

Signed-off-by: Nicolas Toromanoff <nicolas.toromanoff@foss.st.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/stm32/stm32-cryp.c

index faae7ad262ac1fc9770ccf3f27fb3b54ab02ef91..c6640f616d8d1dba1f75840f29b2d04523d48d83 100644 (file)
@@ -232,6 +232,11 @@ static inline int stm32_cryp_wait_busy(struct stm32_cryp *cryp)
                        !(status & SR_BUSY), 10, 100000);
 }
 
+static inline void stm32_cryp_enable(struct stm32_cryp *cryp)
+{
+       writel_relaxed(readl_relaxed(cryp->regs + CRYP_CR) | CR_CRYPEN, cryp->regs + CRYP_CR);
+}
+
 static inline int stm32_cryp_wait_enable(struct stm32_cryp *cryp)
 {
        u32 status;
@@ -534,9 +539,6 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp)
        /* Disable interrupt */
        stm32_cryp_write(cryp, CRYP_IMSCR, 0);
 
-       /* Set key */
-       stm32_cryp_hw_write_key(cryp);
-
        /* Set configuration */
        cfg = CR_DATA8 | CR_FFLUSH;
 
@@ -562,23 +564,36 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp)
        /* AES ECB/CBC decrypt: run key preparation first */
        if (is_decrypt(cryp) &&
            ((hw_mode == CR_AES_ECB) || (hw_mode == CR_AES_CBC))) {
-               stm32_cryp_write(cryp, CRYP_CR, cfg | CR_AES_KP | CR_CRYPEN);
+               /* Configure in key preparation mode */
+               stm32_cryp_write(cryp, CRYP_CR, cfg | CR_AES_KP);
 
+               /* Set key only after full configuration done */
+               stm32_cryp_hw_write_key(cryp);
+
+               /* Start prepare key */
+               stm32_cryp_enable(cryp);
                /* Wait for end of processing */
                ret = stm32_cryp_wait_busy(cryp);
                if (ret) {
                        dev_err(cryp->dev, "Timeout (key preparation)\n");
                        return ret;
                }
-       }
 
-       cfg |= hw_mode;
+               cfg |= hw_mode | CR_DEC_NOT_ENC;
 
-       if (is_decrypt(cryp))
-               cfg |= CR_DEC_NOT_ENC;
+               /* Apply updated config (Decrypt + algo) and flush */
+               stm32_cryp_write(cryp, CRYP_CR, cfg);
+       } else {
+               cfg |= hw_mode;
+               if (is_decrypt(cryp))
+                       cfg |= CR_DEC_NOT_ENC;
 
-       /* Apply config and flush (valid when CRYPEN = 0) */
-       stm32_cryp_write(cryp, CRYP_CR, cfg);
+               /* Apply config and flush */
+               stm32_cryp_write(cryp, CRYP_CR, cfg);
+
+               /* Set key only after configuration done */
+               stm32_cryp_hw_write_key(cryp);
+       }
 
        switch (hw_mode) {
        case CR_AES_GCM:
@@ -606,9 +621,7 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp)
        }
 
        /* Enable now */
-       cfg |= CR_CRYPEN;
-
-       stm32_cryp_write(cryp, CRYP_CR, cfg);
+       stm32_cryp_enable(cryp);
 
        return 0;
 }