libtpmtss: Read RSA public key exponent instead of assuming its value
[strongswan.git] / src / libtpmtss / tpm_tss_tss2_v1.c
index 26fd25c..1c214af 100644 (file)
@@ -69,6 +69,12 @@ struct private_tpm_tss_tss2_t {
         * List of supported algorithms
         */
        TPM_ALG_ID supported_algs[TPM_PT_ALGORITHM_SET];
+
+       /**
+        * Is TPM FIPS 186-4 compliant ?
+        */
+       bool fips_186_4;
+
 };
 
 /**
@@ -154,6 +160,7 @@ static bool get_algs_capability(private_tpm_tss_tss2_t *this)
        TPMS_TAGGED_PROPERTY tp;
        TPMI_YES_NO more_data;
        TPM_ALG_ID alg;
+       bool fips_140_2 = FALSE;
        uint32_t rval, i, offset, revision = 0, year = 0;
        size_t len = BUF_LEN;
        char buf[BUF_LEN], manufacturer[5], vendor_string[17];
@@ -194,12 +201,25 @@ static bool get_algs_capability(private_tpm_tss_tss2_t *this)
                                offset = 4 * (tp.property - TPM_PT_VENDOR_STRING_1);
                                htoun32(vendor_string + offset, tp.value);
                                break;
+                       case TPM_PT_MODES:
+                               if (tp.value & TPMA_MODES_FIPS_140_2)
+                               {
+                                       this->fips_186_4 = fips_140_2 = TRUE;
+                               }
+                               break;
                        default:
                                break;
                }
        }
-       DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u", LABEL, manufacturer,
-                vendor_string, (float)revision/100, year);
+
+       if (!fips_140_2)
+       {
+               this->fips_186_4 = lib->settings->get_bool(lib->settings,
+                                       "%s.plugins.tpm.fips_186_4", FALSE, lib->ns);
+       }
+       DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u %s", LABEL,
+                manufacturer, vendor_string, (float)revision/100, year,
+                fips_140_2 ? "FIPS 140-2" : (this->fips_186_4 ? "FIPS 186-4" : ""));
 
        /* get supported algorithms */
        rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_ALGS,
@@ -401,7 +421,7 @@ METHOD(tpm_tss_t, get_version_info, chunk_t,
 }
 
 /**
- * read the public key portion of a TSS 2.0 AIK key from NVRAM
+ * read the public key portion of a TSS 2.0 key from NVRAM
  */
 bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle,
        TPM2B_PUBLIC *public)
@@ -451,9 +471,9 @@ METHOD(tpm_tss_t, get_public, chunk_t,
        }
 
        aik_blob = chunk_create((u_char*)&public, sizeof(public));
-       DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_blob);
+       DBG3(DBG_LIB, "%s public key blob: %B", LABEL, &aik_blob);
 
-       /* convert TSS 2.0 AIK public key blot into PKCS#1 format */
+       /* convert TSS 2.0 public key blot into PKCS#1 format */
        switch (public.t.publicArea.type)
        {
                case TPM_ALG_RSA:
@@ -461,6 +481,7 @@ METHOD(tpm_tss_t, get_public, chunk_t,
                        TPM2B_PUBLIC_KEY_RSA *rsa;
                        TPMT_RSA_SCHEME *scheme;
                        chunk_t aik_exponent, aik_modulus;
+                       uint32_t exponent;
 
                        scheme = &public.t.publicArea.parameters.rsaDetail.scheme;
                        sig_alg   = scheme->scheme;
@@ -468,14 +489,22 @@ METHOD(tpm_tss_t, get_public, chunk_t,
 
                        rsa = &public.t.publicArea.unique.rsa;
                        aik_modulus = chunk_create(rsa->t.buffer, rsa->t.size);
-                       aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
+                       exponent = public.t.publicArea.parameters.rsaDetail.exponent;
+                       if (!exponent)
+                       {
+                               aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
+                       }
+                       else
+                       {
+                               aik_exponent = chunk_from_thing(exponent);
+                       }
 
-                       /* subjectPublicKeyInfo encoding of AIK RSA key */
+                       /* subjectPublicKeyInfo encoding of RSA public key */
                        if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
                                        NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
                                        CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
                        {
-                               DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key "
+                               DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of public key "
                                                          "failed", LABEL);
                                return chunk_empty;
                        }
@@ -506,7 +535,7 @@ METHOD(tpm_tss_t, get_public, chunk_t,
                        pos += ecc->x.t.size;
                        /* copy y coordinate of ECC point */
                        memcpy(pos, ecc->y.t.buffer, ecc->y.t.size);
-                       /* subjectPublicKeyInfo encoding of AIK ECC key */
+                       /* subjectPublicKeyInfo encoding of ECC public key */
                        aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
                                                        asn1_wrap(ASN1_SEQUENCE, "mm",
                                                                asn1_build_known_oid(OID_EC_PUBLICKEY),
@@ -516,10 +545,10 @@ METHOD(tpm_tss_t, get_public, chunk_t,
                        break;
                }
                default:
-                       DBG1(DBG_PTS, "%s unsupported AIK key type", LABEL);
+                       DBG1(DBG_PTS, "%s unsupported key type", LABEL);
                        return chunk_empty;
        }
-       DBG1(DBG_PTS, "AIK signature algorithm is %N with %N hash",
+       DBG1(DBG_PTS, "signature algorithm is %N with %N hash",
                 tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg);
        return aik_pubkey;
 }
@@ -551,10 +580,14 @@ METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
                        {
                                case TPM_ALG_RSAPSS:
                                {
+                                       ssize_t salt_len;
+
+                                       salt_len = this->fips_186_4 ? RSA_PSS_SALT_LEN_DEFAULT :
+                                                                                                 RSA_PSS_SALT_LEN_MAX;
                                        rsa_pss_params_t pss_params = {
                                                .hash = digest,
                                                .mgf1_hash = digest,
-                                               .salt_len = RSA_PSS_SALT_LEN_MAX,
+                                               .salt_len = salt_len,
                                        };
                                        supported_scheme = (signature_params_t){
                                                .scheme = SIGN_RSA_EMSA_PSS,
@@ -600,7 +633,7 @@ METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
                        break;
                }
                default:
-                       DBG1(DBG_PTS, "%s unsupported AIK key type", LABEL);
+                       DBG1(DBG_PTS, "%s unsupported key type", LABEL);
                        return enumerator_create_empty();
        }
        return enumerator_create_single(signature_params_clone(&supported_scheme),