Bladeren bron

Add support for RSA-PSS keys

Signed-off-by: Steffen Jaeckel <[email protected]>
Steffen Jaeckel 3 maanden geleden
bovenliggende
commit
e25a1438a8

+ 4 - 0
src/headers/tomcrypt_custom.h

@@ -605,6 +605,10 @@
       /* Maximum recursion limit when processing nested ASN.1 types. */
       /* Maximum recursion limit when processing nested ASN.1 types. */
       #define LTC_DER_MAX_RECURSION 30
       #define LTC_DER_MAX_RECURSION 30
    #endif
    #endif
+   #ifndef LTC_DER_OID_DEFAULT_NODES
+      /* Default number of nodes when decoding an OID. */
+      #define LTC_DER_OID_DEFAULT_NODES 12
+   #endif
 #endif
 #endif
 
 
 #if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(LTC_SSH)
 #if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(LTC_SSH)

+ 15 - 1
src/headers/tomcrypt_pk.h

@@ -40,6 +40,7 @@ enum ltc_pka_id {
    LTC_PKA_X25519,
    LTC_PKA_X25519,
    LTC_PKA_ED25519,
    LTC_PKA_ED25519,
    LTC_PKA_DH,
    LTC_PKA_DH,
+   LTC_PKA_RSA_PSS,
    LTC_PKA_NUM
    LTC_PKA_NUM
 };
 };
 
 
@@ -62,7 +63,18 @@ int rand_prime(void *N, long len, prng_state *prng, int wprng);
 /* ---- RSA ---- */
 /* ---- RSA ---- */
 #ifdef LTC_MRSA
 #ifdef LTC_MRSA
 
 
-/** RSA PKCS style key */
+typedef struct ltc_rsa_parameters {
+   /** PSS/OAEP or PKCS #1 v1.5 style
+    *  0 -> PKCS #1 v1.5, 1 -> PSS/OAEP */
+   int pss_oaep;
+   /** saltLength is only defined for PSS
+    * If saltLength == 0 -> OAEP, else -> PSS */
+   unsigned long saltlen;
+   /** hash and MGF hash algorithms */
+   const char *hash_alg, *mgf1_hash_alg;
+} ltc_rsa_parameters;
+
+/** RSA key */
 typedef struct Rsa_key {
 typedef struct Rsa_key {
     /** Type of key, PK_PRIVATE or PK_PUBLIC */
     /** Type of key, PK_PRIVATE or PK_PUBLIC */
     int type;
     int type;
@@ -82,6 +94,8 @@ typedef struct Rsa_key {
     void *dP;
     void *dP;
     /** The d mod (q - 1) CRT param */
     /** The d mod (q - 1) CRT param */
     void *dQ;
     void *dQ;
+    /** Further parameters of the RSA key */
+    ltc_rsa_parameters params;
 } rsa_key;
 } rsa_key;
 
 
 int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);
 int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);

+ 15 - 2
src/headers/tomcrypt_private.h

@@ -60,6 +60,9 @@ enum ltc_oid_id {
    LTC_OID_X25519,
    LTC_OID_X25519,
    LTC_OID_ED25519,
    LTC_OID_ED25519,
    LTC_OID_DH,
    LTC_OID_DH,
+   LTC_OID_RSA_OAEP,
+   LTC_OID_RSA_MGF1,
+   LTC_OID_RSA_PSS,
    LTC_OID_NUM
    LTC_OID_NUM
 };
 };
 
 
@@ -443,8 +446,14 @@ int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long
 
 
 /* ---- DH Routines ---- */
 /* ---- DH Routines ---- */
 #ifdef LTC_MRSA
 #ifdef LTC_MRSA
+typedef enum ltc_rsa_op {
+   LTC_RSA_CRYPT,
+   LTC_RSA_SIGN
+} ltc_rsa_op;
 int rsa_init(rsa_key *key);
 int rsa_init(rsa_key *key);
 void rsa_shrink_key(rsa_key *key);
 void rsa_shrink_key(rsa_key *key);
+int rsa_key_valid_op(const rsa_key *key, ltc_rsa_op op, int padding, int hash_idx);
+int rsa_params_equal(const ltc_rsa_parameters *a, const ltc_rsa_parameters *b);
 int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e,
 int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e,
                       rsa_key *key); /* used by op-tee */
                       rsa_key *key); /* used by op-tee */
 int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key);
 int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key);
@@ -730,7 +739,11 @@ int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned lo
                                             enum ltc_oid_id algorithm, ltc_asn1_type param_type,
                                             enum ltc_oid_id algorithm, ltc_asn1_type param_type,
                                             ltc_asn1_list* parameters, unsigned long *parameters_len,
                                             ltc_asn1_list* parameters, unsigned long *parameters_len,
                                             public_key_decode_cb callback, void *ctx);
                                             public_key_decode_cb callback, void *ctx);
-int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, ltc_asn1_list **spki);
+int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, const ltc_asn1_list **spki);
+int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inlen,
+                                      enum ltc_oid_id algorithm, ltc_asn1_type param_type,
+                                      ltc_asn1_list* parameters, unsigned long *parameters_len,
+                                      public_key_decode_cb callback, void *ctx);
 
 
 /* SUBJECT PUBLIC KEY INFO */
 /* SUBJECT PUBLIC KEY INFO */
 int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
 int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
@@ -741,7 +754,7 @@ int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long i
         enum ltc_oid_id algorithm, void *public_key, unsigned long *public_key_len,
         enum ltc_oid_id algorithm, void *public_key, unsigned long *public_key_len,
         ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len);
         ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len);
 
 
-int x509_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka);
+int x509_get_pka(const ltc_asn1_list *pub, enum ltc_pka_id *pka);
 int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, ltc_asn1_list **root);
 int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, ltc_asn1_list **root);
 
 
 int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2);
 int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2);

+ 1 - 0
src/misc/crypt/crypt.c

@@ -458,6 +458,7 @@ const char *crypt_build_settings =
 #if defined(LTC_DER)
 #if defined(LTC_DER)
     " DER "
     " DER "
     " " NAME_VALUE(LTC_DER_MAX_RECURSION) " "
     " " NAME_VALUE(LTC_DER_MAX_RECURSION) " "
+    " " NAME_VALUE(LTC_DER_OID_DEFAULT_NODES) " "
 #endif
 #endif
 #if defined(LTC_PKCS_1)
 #if defined(LTC_PKCS_1)
     " PKCS#1 "
     " PKCS#1 "

+ 32 - 14
src/pk/asn1/oid/pk_get.c

@@ -7,18 +7,22 @@
 typedef struct {
 typedef struct {
    enum ltc_oid_id id;
    enum ltc_oid_id id;
    enum ltc_pka_id pka;
    enum ltc_pka_id pka;
-   const char* oid;
+   const char *hash;
+   const char *oid;
 } oid_table_entry;
 } oid_table_entry;
 
 
 static const oid_table_entry pka_oids[] = {
 static const oid_table_entry pka_oids[] = {
-                                              { LTC_OID_UNDEF,     LTC_PKA_UNDEF,      NULL },
-                                              { LTC_OID_RSA,       LTC_PKA_RSA,        "1.2.840.113549.1.1.1" },
-                                              { LTC_OID_DSA,       LTC_PKA_DSA,        "1.2.840.10040.4.1" },
-                                              { LTC_OID_EC,        LTC_PKA_EC,         "1.2.840.10045.2.1" },
-                                              { LTC_OID_EC_PRIMEF, LTC_PKA_EC,         "1.2.840.10045.1.1" },
-                                              { LTC_OID_X25519,    LTC_PKA_X25519,     "1.3.101.110" },
-                                              { LTC_OID_ED25519,   LTC_PKA_ED25519,    "1.3.101.112" },
-                                              { LTC_OID_DH,        LTC_PKA_DH,         "1.2.840.113549.1.3.1" },
+                                              { LTC_OID_UNDEF,                LTC_PKA_UNDEF,   NULL,         NULL },
+                                              { LTC_OID_RSA,                  LTC_PKA_RSA,     NULL,         "1.2.840.113549.1.1.1" },
+                                              { LTC_OID_DSA,                  LTC_PKA_DSA,     NULL,         "1.2.840.10040.4.1" },
+                                              { LTC_OID_EC,                   LTC_PKA_EC,      NULL,         "1.2.840.10045.2.1" },
+                                              { LTC_OID_EC_PRIMEF,            LTC_PKA_EC,      NULL,         "1.2.840.10045.1.1" },
+                                              { LTC_OID_X25519,               LTC_PKA_X25519,  NULL,         "1.3.101.110" },
+                                              { LTC_OID_ED25519,              LTC_PKA_ED25519, NULL,         "1.3.101.112" },
+                                              { LTC_OID_DH,                   LTC_PKA_DH,      NULL,         "1.2.840.113549.1.3.1" },
+                                              { LTC_OID_RSA_OAEP,             LTC_PKA_RSA,     NULL,         "1.2.840.113549.1.1.7" },
+                                              { LTC_OID_RSA_MGF1,             LTC_PKA_RSA,     NULL,         "1.2.840.113549.1.1.8" },
+                                              { LTC_OID_RSA_PSS,              LTC_PKA_RSA_PSS, NULL,         "1.2.840.113549.1.1.10" },
 };
 };
 
 
 static LTC_INLINE const oid_table_entry* s_get_entry(enum ltc_oid_id id)
 static LTC_INLINE const oid_table_entry* s_get_entry(enum ltc_oid_id id)
@@ -43,21 +47,35 @@ int pk_get_oid(enum ltc_oid_id id, const char **st)
    return CRYPT_INVALID_ARG;
    return CRYPT_INVALID_ARG;
 }
 }
 
 
-/*
-   Returns the PKA ID requested.
-   @return CRYPT_OK if valid
-*/
-int pk_get_pka_id(enum ltc_oid_id id, enum ltc_pka_id *pka)
+static LTC_INLINE int s_get_values(enum ltc_oid_id id, enum ltc_pka_id *pka, const char **hash)
 {
 {
    const oid_table_entry* e = s_get_entry(id);
    const oid_table_entry* e = s_get_entry(id);
    LTC_ARGCHK(pka != NULL);
    LTC_ARGCHK(pka != NULL);
    if (e != NULL) {
    if (e != NULL) {
       *pka = e->pka;
       *pka = e->pka;
+      if (hash) {
+         *hash = e->hash;
+      } else if (e->hash) {
+         /* If we don't want the hash result, but the entry has a hash, we're most likely
+          * confused and we prefer to stop processing then, instead of continuing with a
+          * maybe wrong assumption.
+          */
+         return CRYPT_INVALID_ARG;
+      }
       return CRYPT_OK;
       return CRYPT_OK;
    }
    }
    return CRYPT_INVALID_ARG;
    return CRYPT_INVALID_ARG;
 }
 }
 
 
+/*
+   Returns the PKA ID requested.
+   @return CRYPT_OK if valid
+*/
+int pk_get_pka_id(enum ltc_oid_id id, enum ltc_pka_id *pka)
+{
+   return s_get_values(id, pka, NULL);
+}
+
 /*
 /*
    Returns the OID ID requested.
    Returns the OID ID requested.
    @return CRYPT_OK if valid
    @return CRYPT_OK if valid

+ 52 - 23
src/pk/asn1/x509/x509_decode_public_key_from_certificate.c

@@ -10,7 +10,7 @@
 #ifdef LTC_DER
 #ifdef LTC_DER
 
 
 /**
 /**
-  Try to decode the public key from a X.509 certificate
+  Process the public key from the SubjectPublicKeyInfo of a X.509 certificate
    @param in               The input buffer
    @param in               The input buffer
    @param inlen            The length of the input buffer
    @param inlen            The length of the input buffer
    @param algorithm        One out of the enum #public_key_algorithms
    @param algorithm        One out of the enum #public_key_algorithms
@@ -19,53 +19,82 @@
    @param parameters_len   [in/out] The number of parameters to include
    @param parameters_len   [in/out] The number of parameters to include
    @param callback         The callback
    @param callback         The callback
    @param ctx              The context passed to the callback
    @param ctx              The context passed to the callback
-   @return CRYPT_OK on success,
-            CRYPT_NOP if no SubjectPublicKeyInfo was found,
-            another error if decoding or memory allocation failed
+   @return CRYPT_OK on success
 */
 */
-int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen,
-                                            enum ltc_oid_id algorithm, ltc_asn1_type param_type,
-                                            ltc_asn1_list* parameters, unsigned long *parameters_len,
-                                            public_key_decode_cb callback, void *ctx)
+int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inlen,
+                                      enum ltc_oid_id algorithm, ltc_asn1_type param_type,
+                                      ltc_asn1_list* parameters, unsigned long *parameters_len,
+                                      public_key_decode_cb callback, void *ctx)
 {
 {
    int err;
    int err;
    unsigned char *tmpbuf = NULL;
    unsigned char *tmpbuf = NULL;
    unsigned long tmpbuf_len;
    unsigned long tmpbuf_len;
-   ltc_asn1_list *decoded_list = NULL, *spki;
-
-   LTC_ARGCHK(in       != NULL);
-   LTC_ARGCHK(inlen    != 0);
-   LTC_ARGCHK(callback != NULL);
 
 
-   if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) {
-      return err;
-   }
+   LTC_ARGCHK(in        != NULL);
+   LTC_ARGCHK(callback  != NULL);
 
 
    if (algorithm == LTC_OID_EC) {
    if (algorithm == LTC_OID_EC) {
-      err = callback(spki->data, spki->size, ctx);
+      err = callback(in, inlen, ctx);
    } else {
    } else {
 
 
       tmpbuf_len = inlen;
       tmpbuf_len = inlen;
       tmpbuf = XCALLOC(1, tmpbuf_len);
       tmpbuf = XCALLOC(1, tmpbuf_len);
       if (tmpbuf == NULL) {
       if (tmpbuf == NULL) {
-          err = CRYPT_MEM;
-          goto LBL_OUT;
+          return CRYPT_MEM;
       }
       }
 
 
-      err = x509_decode_subject_public_key_info(spki->data, spki->size,
+      err = x509_decode_subject_public_key_info(in, inlen,
                                                 algorithm, tmpbuf, &tmpbuf_len,
                                                 algorithm, tmpbuf, &tmpbuf_len,
                                                 param_type, parameters, parameters_len);
                                                 param_type, parameters, parameters_len);
       if (err == CRYPT_OK) {
       if (err == CRYPT_OK) {
          err = callback(tmpbuf, tmpbuf_len, ctx);
          err = callback(tmpbuf, tmpbuf_len, ctx);
-         goto LBL_OUT;
       }
       }
    }
    }
 
 
-LBL_OUT:
-   if (decoded_list) der_free_sequence_flexi(decoded_list);
    if (tmpbuf != NULL) XFREE(tmpbuf);
    if (tmpbuf != NULL) XFREE(tmpbuf);
 
 
    return err;
    return err;
 }
 }
 
 
+/**
+  Try to decode the public key from a X.509 certificate
+   @param in               The input buffer
+   @param inlen            The length of the input buffer
+   @param algorithm        One out of the enum #public_key_algorithms
+   @param param_type       The parameters' type out of the enum ltc_asn1_type
+   @param parameters       The parameters to include
+   @param parameters_len   [in/out] The number of parameters to include
+   @param callback         The callback
+   @param ctx              The context passed to the callback
+   @return CRYPT_OK on success,
+            CRYPT_NOP if no SubjectPublicKeyInfo was found,
+            another error if decoding or memory allocation failed
+*/
+int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen,
+                                            enum ltc_oid_id algorithm, ltc_asn1_type param_type,
+                                            ltc_asn1_list* parameters, unsigned long *parameters_len,
+                                            public_key_decode_cb callback, void *ctx)
+{
+   int err;
+   ltc_asn1_list *decoded_list;
+   const ltc_asn1_list *spki;
+
+   LTC_ARGCHK(in       != NULL);
+   LTC_ARGCHK(inlen    != 0);
+   LTC_ARGCHK(callback != NULL);
+
+   if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) {
+      return err;
+   }
+
+   err = x509_process_public_key_from_spki(spki->data, spki->size,
+                                           algorithm, param_type,
+                                           parameters, parameters_len,
+                                           callback, ctx);
+
+   if (decoded_list) der_free_sequence_flexi(decoded_list);
+
+   return err;
+}
+
 #endif
 #endif

+ 41 - 21
src/pk/asn1/x509/x509_decode_spki.c

@@ -26,10 +26,10 @@
    @param spki             [out] A pointer to the SubjectPublicKeyInfo
    @param spki             [out] A pointer to the SubjectPublicKeyInfo
    @return CRYPT_OK on success, CRYPT_NOP if no SubjectPublicKeyInfo was found, another error if decoding failed
    @return CRYPT_OK on success, CRYPT_NOP if no SubjectPublicKeyInfo was found, another error if decoding failed
 */
 */
-int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, ltc_asn1_list **spki)
+int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, const ltc_asn1_list **spki)
 {
 {
    int err;
    int err;
-   unsigned long tmp_inlen;
+   unsigned long tmp_inlen, n, element_is_spki;
    ltc_asn1_list *decoded_list = NULL, *l;
    ltc_asn1_list *decoded_list = NULL, *l;
 
 
    LTC_ARGCHK(in       != NULL);
    LTC_ARGCHK(in       != NULL);
@@ -49,29 +49,49 @@ int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list
       if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) {
       if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) {
          l = l->child;
          l = l->child;
          if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) {
          if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) {
+            /*    TBSCertificate  ::=  SEQUENCE  {
+             *         version         [0]  EXPLICIT Version DEFAULT v1,
+             *         serialNumber         CertificateSerialNumber,
+             *         signature            AlgorithmIdentifier,
+             *         issuer               Name,
+             *         validity             Validity,
+             *         subject              Name,
+             *         subjectPublicKeyInfo SubjectPublicKeyInfo,
+             *         issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+             *                              -- If present, version MUST be v2 or v3
+             *         subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+             *                              -- If present, version MUST be v2 or v3
+             *         extensions      [3]  EXPLICIT Extensions OPTIONAL
+             *                              -- If present, version MUST be v3
+             *         }
+             */
             l = l->child;
             l = l->child;
 
 
-            /* Move forward in the tree until we find this combination
-                 ...
-                 SEQUENCE
-                     SEQUENCE
-                         OBJECT IDENTIFIER <some PKA OID, e.g. 1.2.840.113549.1.1.1>
-                         NULL
-                     BIT STRING
+            /* `l` points now either to 'version' or 'serialNumber', depending on
+             * whether 'version' is included or defaults to 'v1'.
+             * 'version' is represented as a LTC_ASN1_CUSTOM_TYPE
+             * 'serialNumber' is represented as an LTC_ASN1_INTEGER
+             * Decide now whether to move 5 or 6 elements forward until
+             * `l` should point to subjectPublicKeyInfo.
              */
              */
-            do {
-               /* The additional check for l->data is there to make sure
-                * we won't try to decode a list that has been 'shrunk'
-                */
-               if ((l->type == LTC_ASN1_SEQUENCE)
-                     && (l->data != NULL)
-                     && LOOKS_LIKE_SPKI(l->child)) {
-                  *out = decoded_list;
-                  *spki = l;
-                  return CRYPT_OK;
-               }
+            if (l->type == LTC_ASN1_CUSTOM_TYPE)
+               element_is_spki = 6;
+            else
+               element_is_spki = 5;
+            for (n = 0; n < element_is_spki && l; ++n) {
                l = l->next;
                l = l->next;
-            } while(l);
+            }
+            /* The additional check for l->data is there to make sure
+             * we won't try to decode a list that has been 'shrunk'
+             */
+            if ((l != NULL)
+                  && (l->type == LTC_ASN1_SEQUENCE)
+                  && (l->data != NULL)
+                  && LOOKS_LIKE_SPKI(l->child)) {
+               *out = decoded_list;
+               *spki = l;
+               return CRYPT_OK;
+            }
          }
          }
       }
       }
    }
    }

+ 2 - 2
src/pk/asn1/x509/x509_get_pka.c

@@ -9,7 +9,7 @@
 
 
 #ifdef LTC_DER
 #ifdef LTC_DER
 
 
-int x509_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka)
+int x509_get_pka(const ltc_asn1_list *pub, enum ltc_pka_id *pka)
 {
 {
    der_flexi_check flexi_should[4];
    der_flexi_check flexi_should[4];
    ltc_asn1_list *seqid, *id = NULL;
    ltc_asn1_list *seqid, *id = NULL;
@@ -17,7 +17,7 @@ int x509_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka)
    int err;
    int err;
    unsigned long n = 0;
    unsigned long n = 0;
    LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seqid);
    LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seqid);
-   LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_BIT_STRING, NULL);
+   LTC_SET_DER_FLEXI_CHECK_OPT(flexi_should, n++, LTC_ASN1_BIT_STRING, NULL);
    LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL);
    LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL);
    if ((err = der_flexi_sequence_cmp(pub, flexi_should)) != CRYPT_OK) {
    if ((err = der_flexi_sequence_cmp(pub, flexi_should)) != CRYPT_OK) {
       return err;
       return err;

+ 3 - 1
src/pk/asn1/x509/x509_import_spki.c

@@ -14,6 +14,7 @@ typedef int (*import_fn)(const unsigned char *, unsigned long, void*);
 static const import_fn s_import_x509_fns[LTC_PKA_NUM] = {
 static const import_fn s_import_x509_fns[LTC_PKA_NUM] = {
 #ifdef LTC_MRSA
 #ifdef LTC_MRSA
                                                 [LTC_PKA_RSA] = (import_fn)rsa_import_x509,
                                                 [LTC_PKA_RSA] = (import_fn)rsa_import_x509,
+                                                [LTC_PKA_RSA_PSS] = (import_fn)rsa_import_x509,
 #endif
 #endif
 #ifdef LTC_MDSA
 #ifdef LTC_MDSA
                                                 [LTC_PKA_DSA] = (import_fn)dsa_import,
                                                 [LTC_PKA_DSA] = (import_fn)dsa_import,
@@ -30,7 +31,8 @@ static const import_fn s_import_x509_fns[LTC_PKA_NUM] = {
 int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, ltc_asn1_list **root)
 int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, ltc_asn1_list **root)
 {
 {
    enum ltc_pka_id pka = LTC_PKA_UNDEF;
    enum ltc_pka_id pka = LTC_PKA_UNDEF;
-   ltc_asn1_list *d, *spki;
+   ltc_asn1_list *d;
+   const ltc_asn1_list *spki;
    int err;
    int err;
    if ((err = x509_decode_spki(asn1_cert, asn1_len, &d, &spki)) != CRYPT_OK) {
    if ((err = x509_decode_spki(asn1_cert, asn1_len, &d, &spki)) != CRYPT_OK) {
       return err;
       return err;

+ 1 - 0
src/pk/pka_key.c

@@ -30,6 +30,7 @@ void pka_key_free(ltc_pka_key *key)
 #endif
 #endif
          break;
          break;
       case LTC_PKA_RSA:
       case LTC_PKA_RSA:
+      case LTC_PKA_RSA_PSS:
 #if defined(LTC_MRSA)
 #if defined(LTC_MRSA)
          rsa_free(&key->u.rsa);
          rsa_free(&key->u.rsa);
 #endif
 #endif

+ 2 - 10
src/pk/rsa/rsa_decrypt_key.c

@@ -45,16 +45,8 @@ int rsa_decrypt_key_ex(const unsigned char *in,             unsigned long  inlen
   *stat = 0;
   *stat = 0;
 
 
   /* valid padding? */
   /* valid padding? */
-  if ((padding != LTC_PKCS_1_V1_5) &&
-      (padding != LTC_PKCS_1_OAEP)) {
-    return CRYPT_PK_INVALID_PADDING;
-  }
-
-  if (padding == LTC_PKCS_1_OAEP) {
-    /* valid hash ? */
-    if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
-       return err;
-    }
+  if ((err = rsa_key_valid_op(key, LTC_RSA_CRYPT, padding, mgf_hash)) != CRYPT_OK) {
+    return err;
   }
   }
 
 
   /* get modulus len in bits */
   /* get modulus len in bits */

+ 2 - 10
src/pk/rsa/rsa_encrypt_key.c

@@ -41,9 +41,8 @@ int rsa_encrypt_key_ex(const unsigned char *in,       unsigned long  inlen,
   LTC_ARGCHK(key    != NULL);
   LTC_ARGCHK(key    != NULL);
 
 
   /* valid padding? */
   /* valid padding? */
-  if ((padding != LTC_PKCS_1_V1_5) &&
-      (padding != LTC_PKCS_1_OAEP)) {
-    return CRYPT_PK_INVALID_PADDING;
+  if ((err = rsa_key_valid_op(key, LTC_RSA_CRYPT, padding, mgf_hash)) != CRYPT_OK) {
+    return err;
   }
   }
 
 
   /* valid prng? */
   /* valid prng? */
@@ -51,13 +50,6 @@ int rsa_encrypt_key_ex(const unsigned char *in,       unsigned long  inlen,
      return err;
      return err;
   }
   }
 
 
-  if (padding == LTC_PKCS_1_OAEP) {
-    /* valid hash? */
-    if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
-       return err;
-    }
-  }
-
   /* get modulus len in bits */
   /* get modulus len in bits */
   modulus_bitlen = ltc_mp_count_bits( (key->N));
   modulus_bitlen = ltc_mp_count_bits( (key->N));
 
 

+ 24 - 42
src/pk/rsa/rsa_import.c

@@ -9,6 +9,18 @@
 
 
 #ifdef LTC_MRSA
 #ifdef LTC_MRSA
 
 
+#ifndef S_RSA_DECODE
+#define S_RSA_DECODE
+static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+   /* now it should be SEQUENCE { INTEGER, INTEGER } */
+   return der_decode_sequence_multi(in, inlen,
+                                        LTC_ASN1_INTEGER, 1UL, key->N,
+                                        LTC_ASN1_INTEGER, 1UL, key->e,
+                                        LTC_ASN1_EOL,     0UL, NULL);
+}
+#endif
+
 
 
 /**
 /**
   Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only]
   Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only]
@@ -33,10 +45,7 @@ int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key)
       /* the version would fit into an LTC_ASN1_SHORT_INTEGER
       /* the version would fit into an LTC_ASN1_SHORT_INTEGER
        * so we try to decode as a public key
        * so we try to decode as a public key
        */
        */
-      if ((err = der_decode_sequence_multi(in, inlen,
-                                     LTC_ASN1_INTEGER, 1UL, key->N,
-                                     LTC_ASN1_INTEGER, 1UL, key->e,
-                                     LTC_ASN1_EOL,     0UL, NULL)) == CRYPT_OK) {
+      if ((err = s_rsa_decode(in, inlen, key)) == CRYPT_OK) {
          key->type = PK_PUBLIC;
          key->type = PK_PUBLIC;
       }
       }
       goto LBL_OUT;
       goto LBL_OUT;
@@ -85,57 +94,30 @@ LBL_OUT:
 int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
 int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
 {
 {
    int           err;
    int           err;
-   unsigned char *tmpbuf=NULL;
-   unsigned long tmpbuf_len, len;
 
 
    LTC_ARGCHK(in          != NULL);
    LTC_ARGCHK(in          != NULL);
    LTC_ARGCHK(key         != NULL);
    LTC_ARGCHK(key         != NULL);
    LTC_ARGCHK(ltc_mp.name != NULL);
    LTC_ARGCHK(ltc_mp.name != NULL);
 
 
+   if ((err = rsa_import_x509(in, inlen, key)) == CRYPT_OK) { /* SubjectPublicKeyInfo format */
+      return CRYPT_OK;
+   }
+
    /* init key */
    /* init key */
    if ((err = rsa_init(key)) != CRYPT_OK) {
    if ((err = rsa_init(key)) != CRYPT_OK) {
       return err;
       return err;
    }
    }
 
 
-   /* see if the OpenSSL DER format RSA public key will work */
-   tmpbuf_len = inlen;
-   tmpbuf = XCALLOC(1, tmpbuf_len);
-   if (tmpbuf == NULL) {
-       err = CRYPT_MEM;
-       goto LBL_ERR;
-   }
-
-   len = 0;
-   err = x509_decode_subject_public_key_info(in, inlen,
-        LTC_OID_RSA, tmpbuf, &tmpbuf_len,
-        LTC_ASN1_NULL, NULL, &len);
-
-   if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */
-
-      /* now it should be SEQUENCE { INTEGER, INTEGER } */
-      if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len,
-                                           LTC_ASN1_INTEGER, 1UL, key->N,
-                                           LTC_ASN1_INTEGER, 1UL, key->e,
-                                           LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
-         goto LBL_ERR;
+   if ((err = x509_process_public_key_from_spki(in, inlen,
+                                                LTC_OID_RSA,
+                                                LTC_ASN1_NULL, NULL, NULL,
+                                                (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) {
+      /* not SSL public key, try to match against PKCS #1 standards */
+      if ((err = rsa_import_pkcs1(in, inlen, key)) != CRYPT_OK) {
+         rsa_free(key);
       }
       }
-      key->type = PK_PUBLIC;
-      err = CRYPT_OK;
-      goto LBL_FREE;
    }
    }
 
 
-   /* not SSL public key, try to match against PKCS #1 standards */
-   if ((err = rsa_import_pkcs1(in, inlen, key)) == CRYPT_OK) {
-      goto LBL_FREE;
-   }
-
-LBL_ERR:
-   rsa_free(key);
-
-LBL_FREE:
-   if (tmpbuf != NULL) {
-      XFREE(tmpbuf);
-   }
    return err;
    return err;
 }
 }
 
 

+ 158 - 3
src/pk/rsa/rsa_import_x509.c

@@ -9,6 +9,8 @@
 
 
 #ifdef LTC_MRSA
 #ifdef LTC_MRSA
 
 
+#ifndef S_RSA_DECODE
+#define S_RSA_DECODE
 static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *key)
 static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *key)
 {
 {
    /* now it should be SEQUENCE { INTEGER, INTEGER } */
    /* now it should be SEQUENCE { INTEGER, INTEGER } */
@@ -17,6 +19,153 @@ static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *k
                                         LTC_ASN1_INTEGER, 1UL, key->e,
                                         LTC_ASN1_INTEGER, 1UL, key->e,
                                         LTC_ASN1_EOL,     0UL, NULL);
                                         LTC_ASN1_EOL,     0UL, NULL);
 }
 }
+#endif
+
+typedef struct rsa_pss_parameters_data {
+   ltc_asn1_list params[4], inner[4], hash_alg[2], mgf[2], mgf_hash_alg[2];
+   unsigned long hash_alg_oid[LTC_DER_OID_DEFAULT_NODES];
+   unsigned long mgf_alg_oid[LTC_DER_OID_DEFAULT_NODES];
+   unsigned long mgf1_hash_alg_oid[LTC_DER_OID_DEFAULT_NODES];
+   unsigned long salt_length, trailer_field;
+} rsa_pss_parameters_data;
+
+static LTC_INLINE void s_rsa_pss_parameters_data_setup(rsa_pss_parameters_data *d)
+{
+   unsigned long n;
+   /* RSASSA-PSS
+    *
+    *    RSASSA-PSS-params ::= SEQUENCE {
+    *        hashAlgorithm      [0] HashAlgorithm      DEFAULT sha1,
+    *        maskGenAlgorithm   [1] MaskGenAlgorithm   DEFAULT mgf1SHA1,
+    *        saltLength         [2] INTEGER            DEFAULT 20,
+    *        trailerField       [3] TrailerField       DEFAULT trailerFieldBC
+    *    }
+    */
+
+   /*        HashAlgorithm ::= AlgorithmIdentifier {
+    *           {OAEP-PSSDigestAlgorithms}
+    *        }
+    */
+   LTC_SET_ASN1(d->hash_alg, 0, LTC_ASN1_OBJECT_IDENTIFIER, d->hash_alg_oid, LTC_ARRAY_SIZE(d->hash_alg_oid));
+   LTC_SET_ASN1(d->hash_alg, 1, LTC_ASN1_NULL, NULL, 0);
+   d->hash_alg[1].optional = 1;
+
+   /*        MaskGenAlgorithm ::= AlgorithmIdentifier { {PKCS1MGFAlgorithms} } */
+   LTC_SET_ASN1(d->mgf_hash_alg, 0, LTC_ASN1_OBJECT_IDENTIFIER, d->mgf1_hash_alg_oid, LTC_ARRAY_SIZE(d->mgf1_hash_alg_oid));
+   LTC_SET_ASN1(d->mgf_hash_alg, 1, LTC_ASN1_NULL, NULL, 0);
+   d->mgf_hash_alg[1].optional = 1;
+
+   /*        PKCS1MGFAlgorithms    ALGORITHM-IDENTIFIER ::= {
+    *            { OID id-mgf1 PARAMETERS HashAlgorithm },
+    *            ... -- Allows for future expansion --
+    *        }
+    */
+   LTC_SET_ASN1(d->mgf, 0, LTC_ASN1_OBJECT_IDENTIFIER, d->mgf_alg_oid, LTC_ARRAY_SIZE(d->mgf_alg_oid));
+   LTC_SET_ASN1(d->mgf, 1, LTC_ASN1_SEQUENCE, d->mgf_hash_alg, LTC_ARRAY_SIZE(d->mgf_hash_alg));
+
+   LTC_SET_ASN1(d->inner, 0, LTC_ASN1_SEQUENCE, d->hash_alg, LTC_ARRAY_SIZE(d->hash_alg));
+   LTC_SET_ASN1(d->inner, 1, LTC_ASN1_SEQUENCE, d->mgf, LTC_ARRAY_SIZE(d->mgf));
+   LTC_SET_ASN1(d->inner, 2, LTC_ASN1_SHORT_INTEGER, &d->salt_length, 1UL);
+   LTC_SET_ASN1(d->inner, 3, LTC_ASN1_SHORT_INTEGER, &d->trailer_field, 1UL);
+
+   LTC_SET_ASN1_CUSTOM_CONSTRUCTED(d->params, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, d->inner);     /* context specific 0 */
+   LTC_SET_ASN1_CUSTOM_CONSTRUCTED(d->params, 1, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, d->inner + 1); /* context specific 1 */
+   LTC_SET_ASN1_CUSTOM_CONSTRUCTED(d->params, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 2, d->inner + 2); /* context specific 2 */
+   LTC_SET_ASN1_CUSTOM_CONSTRUCTED(d->params, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 3, d->inner + 3); /* context specific 3 */
+   for (n = 0; n < 4; ++n) {
+      d->params[n].optional = 1;
+   }
+}
+
+int rsa_decode_parameters(const ltc_asn1_list *parameters, ltc_rsa_parameters *rsa_params)
+{
+   rsa_pss_parameters_data d;
+   unsigned long n;
+   enum ltc_oid_id oid_id;
+   int           err, idx;
+
+   s_rsa_pss_parameters_data_setup(&d);
+
+   if ((err = der_decode_sequence(parameters->data, parameters->size, d.params, 4)) != CRYPT_OK) {
+      return err;
+   }
+
+   rsa_params->saltlen = 20;
+   rsa_params->hash_alg = rsa_params->mgf1_hash_alg = "sha1";
+
+   for (n = 0; n < 4; ++n) {
+      if (d.params[n].used == 0)
+         continue;
+      switch (n) {
+         case 0:
+            idx = find_hash_oid(d.hash_alg->data, d.hash_alg->size);
+            if (idx == -1) {
+               return CRYPT_INVALID_HASH;
+            }
+            rsa_params->hash_alg = hash_descriptor[idx].name;
+            break;
+         case 1:
+            if ((err = pk_get_oid_from_asn1(&d.mgf[0], &oid_id)) != CRYPT_OK) {
+               return err;
+            }
+            if (oid_id != LTC_OID_RSA_MGF1) {
+               return CRYPT_PK_ASN1_ERROR;
+            }
+            idx = find_hash_oid(d.mgf_hash_alg->data, d.mgf_hash_alg->size);
+            if (idx == -1) {
+               return CRYPT_INVALID_HASH;
+            }
+            rsa_params->mgf1_hash_alg = hash_descriptor[idx].name;
+            break;
+         case 2:
+            rsa_params->saltlen = d.salt_length;
+            break;
+         case 3:
+            if (d.trailer_field != 1) {
+               return CRYPT_PK_ASN1_ERROR;
+            }
+            break;
+         default:
+            return CRYPT_PK_ASN1_ERROR;
+      }
+   }
+
+
+   rsa_params->pss_oaep = 1;
+
+   return CRYPT_OK;
+}
+
+static int s_rsa_import_pss(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+   rsa_pss_parameters_data d;
+   ltc_asn1_list *decoded_list;
+   const ltc_asn1_list *spki;
+   int           err;
+   unsigned long n_params = LTC_ARRAY_SIZE(d.params);
+
+   if ((err = x509_process_public_key_from_spki(in, inlen,
+                                                LTC_OID_RSA_PSS,
+                                                LTC_ASN1_NULL, NULL, NULL,
+                                                (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) {
+      if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) {
+         return err;
+      }
+      if ((err = x509_process_public_key_from_spki(spki->data, spki->size,
+                                              LTC_OID_RSA_PSS,
+                                              LTC_ASN1_NULL, NULL, NULL,
+                                              (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) {
+         s_rsa_pss_parameters_data_setup(&d);
+         err = x509_process_public_key_from_spki(spki->data, spki->size,
+                                                 LTC_OID_RSA_PSS,
+                                                 LTC_ASN1_SEQUENCE, d.params, &n_params,
+                                                 (public_key_decode_cb)s_rsa_decode, key);
+      }
+   }
+
+   der_free_sequence_flexi(decoded_list);
+   return err;
+}
 
 
 /**
 /**
   Import an RSA key from a X.509 certificate
   Import an RSA key from a X.509 certificate
@@ -41,12 +190,18 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
    if ((err = x509_decode_public_key_from_certificate(in, inlen,
    if ((err = x509_decode_public_key_from_certificate(in, inlen,
                                                       LTC_OID_RSA,
                                                       LTC_OID_RSA,
                                                       LTC_ASN1_NULL, NULL, NULL,
                                                       LTC_ASN1_NULL, NULL, NULL,
-                                                      (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) {
-      rsa_free(key);
-   } else {
+                                                      (public_key_decode_cb)s_rsa_decode, key)) == CRYPT_OK) {
       key->type = PK_PUBLIC;
       key->type = PK_PUBLIC;
+      return CRYPT_OK;
    }
    }
 
 
+   if ((err = s_rsa_import_pss(in, inlen, key)) == CRYPT_OK) {
+      key->type = PK_PUBLIC;
+      return CRYPT_OK;
+   }
+
+   rsa_free(key);
+
    return err;
    return err;
 }
 }
 
 

+ 85 - 0
src/pk/rsa/rsa_key.c

@@ -85,6 +85,7 @@ void rsa_shrink_key(rsa_key *key)
 int rsa_init(rsa_key *key)
 int rsa_init(rsa_key *key)
 {
 {
    LTC_ARGCHK(key != NULL);
    LTC_ARGCHK(key != NULL);
+   XMEMSET(&key->params, 0, sizeof(key->params));
    return ltc_mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, LTC_NULL);
    return ltc_mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, LTC_NULL);
 }
 }
 
 
@@ -96,6 +97,90 @@ void rsa_free(rsa_key *key)
 {
 {
    LTC_ARGCHKVD(key != NULL);
    LTC_ARGCHKVD(key != NULL);
    ltc_mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, LTC_NULL);
    ltc_mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, LTC_NULL);
+   XMEMSET(&key->params, 0, sizeof(key->params));
+}
+
+static LTC_INLINE int s_rsa_key_valid_pss_algs(const rsa_key *key, int padding, int hash_idx)
+{
+   if (!key->params.pss_oaep) {
+      return CRYPT_OK;
+   }
+   if (padding != LTC_PKCS_1_PSS) {
+      return CRYPT_PK_TYPE_MISMATCH;
+   }
+   if (key->params.hash_alg == NULL || find_hash(key->params.hash_alg) != hash_idx) {
+      return CRYPT_INVALID_HASH;
+   }
+   if (key->params.mgf1_hash_alg == NULL) {
+      return CRYPT_INVALID_HASH;
+   }
+   return hash_is_valid(find_hash(key->params.mgf1_hash_alg));
+}
+
+static LTC_INLINE int s_rsa_key_valid_sign(const rsa_key *key, int padding, int hash_idx)
+{
+   if ((padding != LTC_PKCS_1_V1_5) &&
+       (padding != LTC_PKCS_1_PSS) &&
+       (padding != LTC_PKCS_1_V1_5_NA1)) {
+     return CRYPT_PK_INVALID_PADDING;
+   }
+
+   if (padding != LTC_PKCS_1_V1_5_NA1) {
+      int err;
+      /* valid hash ? */
+      if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+        return err;
+      }
+   }
+   return s_rsa_key_valid_pss_algs(key, padding, hash_idx);
+}
+
+static LTC_INLINE int s_rsa_key_valid_crypt(const rsa_key *key, int padding, int hash_idx)
+{
+   if ((padding != LTC_PKCS_1_V1_5) &&
+       (padding != LTC_PKCS_1_OAEP)) {
+     return CRYPT_PK_INVALID_PADDING;
+   }
+
+   if (padding == LTC_PKCS_1_OAEP) {
+      int err;
+      /* valid hash? */
+      if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+        return err;
+      }
+   }
+   return s_rsa_key_valid_pss_algs(key, padding, hash_idx);
+}
+
+int rsa_key_valid_op(const rsa_key *key, ltc_rsa_op op, int padding, int hash_idx)
+{
+   switch (op) {
+      case LTC_RSA_SIGN:
+         return s_rsa_key_valid_sign(key, padding, hash_idx);
+      case LTC_RSA_CRYPT:
+         return s_rsa_key_valid_crypt(key, padding, hash_idx);
+      default:
+         return CRYPT_ERROR;
+   }
+}
+
+int rsa_params_equal(const ltc_rsa_parameters *a, const ltc_rsa_parameters *b)
+{
+   if (!a->pss_oaep)
+      return 0;
+   if (a->pss_oaep != b->pss_oaep)
+      return 0;
+   if (a->saltlen != b->saltlen)
+      return 0;
+   if (!a->hash_alg || !b->hash_alg)
+      return 0;
+   if (XSTRCMP(a->hash_alg, b->hash_alg))
+      return 0;
+   if (!a->mgf1_hash_alg || !b->mgf1_hash_alg)
+      return 0;
+   if (XSTRCMP(a->mgf1_hash_alg, b->mgf1_hash_alg))
+      return 0;
+   return 1;
 }
 }
 
 
 #endif
 #endif

+ 2 - 11
src/pk/rsa/rsa_sign_hash.c

@@ -40,10 +40,8 @@ int rsa_sign_hash_ex(const unsigned char *in,       unsigned long  inlen,
    LTC_ARGCHK(key      != NULL);
    LTC_ARGCHK(key      != NULL);
 
 
    /* valid padding? */
    /* valid padding? */
-   if ((padding != LTC_PKCS_1_V1_5) &&
-       (padding != LTC_PKCS_1_PSS) &&
-       (padding != LTC_PKCS_1_V1_5_NA1)) {
-     return CRYPT_PK_INVALID_PADDING;
+   if ((err = rsa_key_valid_op(key, LTC_RSA_SIGN, padding, hash_idx)) != CRYPT_OK) {
+     return err;
    }
    }
 
 
    if (padding == LTC_PKCS_1_PSS) {
    if (padding == LTC_PKCS_1_PSS) {
@@ -53,13 +51,6 @@ int rsa_sign_hash_ex(const unsigned char *in,       unsigned long  inlen,
      }
      }
    }
    }
 
 
-   if (padding != LTC_PKCS_1_V1_5_NA1) {
-     /* valid hash ? */
-     if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
-        return err;
-     }
-   }
-
    /* get modulus len in bits */
    /* get modulus len in bits */
    modulus_bitlen = ltc_mp_count_bits((key->N));
    modulus_bitlen = ltc_mp_count_bits((key->N));
 
 

+ 2 - 12
src/pk/rsa/rsa_verify_hash.c

@@ -42,18 +42,8 @@ int rsa_verify_hash_ex(const unsigned char *sig,            unsigned long  sigle
   *stat = 0;
   *stat = 0;
 
 
   /* valid padding? */
   /* valid padding? */
-
-  if ((padding != LTC_PKCS_1_V1_5) &&
-      (padding != LTC_PKCS_1_PSS) &&
-      (padding != LTC_PKCS_1_V1_5_NA1)) {
-    return CRYPT_PK_INVALID_PADDING;
-  }
-
-  if (padding != LTC_PKCS_1_V1_5_NA1) {
-    /* valid hash ? */
-    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
-       return err;
-    }
+  if ((err = rsa_key_valid_op(key, LTC_RSA_SIGN, padding, hash_idx)) != CRYPT_OK) {
+    return err;
   }
   }
 
 
   /* get modulus len in bits */
   /* get modulus len in bits */