tpm2-software / tpm2-pkcs11

A PKCS#11 interface for TPM2 hardware
https://tpm2-software.github.io
Other
278 stars 104 forks source link

Error while decrypting in padding mode #841

Open peshevod opened 1 year ago

peshevod commented 1 year ago

Hello! Trying to use this module for java:

package testPkcs11;

import javax.crypto.; import javax.crypto.spec.IvParameterSpec; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.security.; import java.security.cert.CertificateException;

public class TestPkcs11 {

public void test()
{
    String pin=System.getProperty("pin");
    String alias= System.getProperty("key.name");
    String keyStorePassword=System.getProperty("keystore.password");
    Path configPath=Path.of("./tpm.config");
    String cfg="name = tpm\n" +
            "library = /usr/lib/x86_64-linux-gnu/pkcs11/libtpm2_pkcs11.so\n" +
            "slotListIndex = 0\n" +
            "attributes(generate, *, *) = {\n" +
            "   CKA_TOKEN = true\n" +
            "}\n" +
            "attributes(generate, CKO_CERTIFICATE, *) = {\n" +
            "   CKA_PRIVATE = false\n" +
            "}\n" +
            "attributes(generate, CKO_PUBLIC_KEY, *) = {\n" +
            "   CKA_PRIVATE = false\n" +
            "}\n";

    try {
        Files.write(configPath,cfg.getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
        Provider pkcs11Provider = Security.getProvider("SunPKCS11");
        pkcs11Provider = pkcs11Provider.configure(configPath.toAbsolutePath().toString());
        KeyStore keyStore = KeyStore.getInstance("PKCS11", pkcs11Provider);
        keyStore.load(null, pin.toCharArray());

        SecretKey secretKey=((KeyStore.SecretKeyEntry)keyStore.getEntry(alias, new KeyStore.PasswordProtection(keyStorePassword.toCharArray()))).getSecretKey();

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding",pkcs11Provider);
        byte[] iv=new byte[16];
        for (int i = 0; i < iv.length; i++) iv[i]=' ';
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));

        byte[] plainText="This is the text for tpm encryption with tpm2-pkcs11 module".getBytes(StandardCharsets.UTF_8);
        byte[] encryptedText=cipher.doFinal(plainText);
        System.out.println("plainText.len="+plainText.length+" encryptedText.len="+encryptedText.length);

        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
        byte[] decryptedText=cipher.doFinal(encryptedText);
        System.out.println("decryptedText.len="+decryptedText.length+" decryptedText='"+new String(decryptedText,StandardCharsets.UTF_8)+"'");

    } catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException |
             UnrecoverableEntryException | NoSuchPaddingException | InvalidKeyException |
             InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
        System.out.println(e);
        return;
    }
}

public static void main(String[] args)
{
    TestPkcs11 test=new TestPkcs11();
    test.test();
    System.exit(0);
}

}

and received error:

/lib/jvm/jdk-17.0.2/bin/java -Dpin=**** -Dkey.name=admin -Dkeystore.password=**** -javaagent:/home/ilya/idea-IC-231.8770.65/lib/idea_rt.jar=45183:/home/ilya/idea-IC-231.8770.65/bin -Dfile.encoding=UTF-8 -classpath /home/ilya/IdeaProjects/TestPkcs11/out/production/classes testPkcs11.TestPkcs11 WARNING: Getting tokens from fapi backend failed. plainText.len=59 encryptedText.len=64 ERROR: Internal buffer too small extralen=48 ERROR: Nonsensical pad value, got: 0, expected 1-16 Exception in thread "main" java.security.ProviderException: update() failed at jdk.crypto.cryptoki/sun.security.pkcs11.P11Cipher.implUpdate(P11Cipher.java:668) at jdk.crypto.cryptoki/sun.security.pkcs11.P11Cipher.engineUpdate(P11Cipher.java:553) at jdk.crypto.cryptoki/sun.security.pkcs11.P11Cipher.engineDoFinal(P11Cipher.java:582) at jdk.crypto.cryptoki/sun.security.pkcs11.P11Cipher.engineDoFinal(P11Cipher.java:568) at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2205) at testPkcs11.TestPkcs11.test(TestPkcs11.java:53) at testPkcs11.TestPkcs11.main(TestPkcs11.java:67) Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_GENERAL_ERROR at jdk.crypto.cryptoki/sun.security.pkcs11.wrapper.PKCS11.C_DecryptUpdate(Native Method) at jdk.crypto.cryptoki/sun.security.pkcs11.P11Cipher.implUpdate(P11Cipher.java:648) ... 6 more

Process finished with exit code 1

It seems to me there are error in tpm.c code function do_buffered_encdec in this part: ...

bool hold_block_back = encdec == DECRYPT
        && !is_final
        && blocks > 0
        && extralen == 0
        && tpm_enc_data->mech.mechanism == CKM_AES_CBC_PAD;

if (hold_block_back) {
    blocks--;
    extralen = blocks == 0 ? 16 : blocks * 16;
    modified_full_buffer_len = blocks * 16;
}

...

If I change string

    extralen = blocks == 0 ? 16 : blocks * 16;

to

    extralen = 16;

it works.