]> git.saurik.com Git - apple/xnu.git/blobdiff - EXTERNAL_HEADERS/corecrypto/ccrsa.h
xnu-7195.101.1.tar.gz
[apple/xnu.git] / EXTERNAL_HEADERS / corecrypto / ccrsa.h
index 97a88529a08991a309e0546fc9b59e9659703f2b..d0b459fda8ca01daf1d59af25f3d00122b349067 100644 (file)
@@ -1,11 +1,12 @@
-/*
- *  ccrsa.h
- *  corecrypto
- *
- *  Created on 11/16/2010
- *
- *  Copyright (c) 2010,2011,2012,2014,2015 Apple Inc. All rights reserved.
+/* Copyright (c) (2010,2011,2012,2014,2015,2016,2017,2018,2019,2020) Apple Inc. All rights reserved.
  *
+ * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which
+ * is contained in the License.txt file distributed with corecrypto) and only to 
+ * people who accept that license. IMPORTANT:  Any license rights granted to you by 
+ * Apple Inc. (if any) are limited to internal use within your organization only on 
+ * devices and computers you own or control, for the sole purpose of verifying the 
+ * security characteristics and correct functioning of the Apple Software.  You may 
+ * not, directly or indirectly, redistribute the Apple Software or any portions thereof.
  */
 
 #ifndef _CORECRYPTO_CCRSA_H_
 #include <corecrypto/ccdigest.h>
 #include <corecrypto/ccrng.h>
 #include <corecrypto/cczp.h>
+#include <corecrypto/cc_fault_canary.h>
 #include <stdbool.h>
 
 // Apple does not generate keys of greater than 4096 bits
 // This limit is relaxed to accommodate potential third-party consumers
 #define CCRSA_KEYGEN_MAX_NBITS 8192
 
-// Program error: buffer too small or encrypted message is too small
-#define CCRSA_INVALID_INPUT        -1
-// Invalid crypto configuration: Hash length versus RSA key size
-#define CCRSA_INVALID_CONFIG       -2
-// The data is invalid (we won't say more for security
-#define CCRSA_DECRYPTION_ERROR     -3
-
-#define CCRSA_ENCODING_ERROR       -4
-#define CCRSA_DECODING_ERROR       -5
-#define CCRSA_SIGNATURE_GEN_ERROR  -6
-
 struct ccrsa_full_ctx {
     __CCZP_ELEMENTS_DEFINITIONS(pb_)
 } CC_ALIGNED(CCN_UNIT_SIZE);
@@ -44,35 +35,12 @@ struct ccrsa_priv_ctx {
     __CCZP_ELEMENTS_DEFINITIONS(pv_)
 } CC_ALIGNED(CCN_UNIT_SIZE);
 
-
-#if CORECRYPTO_USE_TRANSPARENT_UNION
-    typedef union {
-        cczp_t zp;
-        struct ccrsa_pub_ctx* pub;
-        struct ccrsa_full_ctx *full;
-    } ccrsa_full_ctx_t __attribute__((transparent_union));
-    typedef struct ccrsa_full_ctx ccrsa_full_ctx;
-    typedef struct ccrsa_priv_ctx ccrsa_priv_ctx;
-
-    typedef union {
-        cczp_t zp;
-        ccrsa_priv_ctx *priv;
-    } ccrsa_priv_ctx_t __attribute__((transparent_union));
-
-
-typedef ccrsa_full_ctx_t ccrsa_pub_ctx_t;
-typedef struct ccrsa_pub_ctx ccrsa_pub_ctx;
-
-#else
-    typedef struct ccrsa_full_ctx* ccrsa_full_ctx_t;
-    typedef struct ccrsa_pub_ctx* ccrsa_pub_ctx_t;
-    typedef struct ccrsa_priv_ctx* ccrsa_priv_ctx_t;
-#endif
-
-
+typedef struct ccrsa_full_ctx* ccrsa_full_ctx_t;
+typedef struct ccrsa_pub_ctx* ccrsa_pub_ctx_t;
+typedef struct ccrsa_priv_ctx* ccrsa_priv_ctx_t;
 
 /*
- public key cczp      d=e^-1 mod phi(m) priv key cczp             priv key cczq             dp, dq, qinv
+ public key cczp   d=e^-1 mod lambda(m) priv key cczp             priv key cczq             dp, dq, qinv
  |                              |       |                         |                         |
  |                              |       |                         |                         |
  +-------+------+-------+------++------++-------+------+---------++-------+------+---------++-------+-------+---------+
@@ -101,19 +69,9 @@ typedef struct ccrsa_pub_ctx ccrsa_pub_ctx;
 // The offsets are computed using pb_ccn. If any object other than ccrsa_full_ctx_t
 // or ccrsa_pub_ctx_t is passed to the macros, compiler error is generated.
 
-
-
-#if CORECRYPTO_USE_TRANSPARENT_UNION
-//#define ccrsa_ctx_zm(_ctx_)        (((ccrsa_pub_ctx_t)(_ctx_)).zp)
-
-    CC_CONST CC_INLINE cczp_t ccrsa_ctx_zm(ccrsa_full_ctx_t _ctx_) { return ((cczp_t)(struct cczp *)((_ctx_).full)); }
-    CC_CONST CC_INLINE cc_unit  *ccrsa_ctx_m(ccrsa_full_ctx_t _ctx_){ return        ((_ctx_).full->pb_ccn);}
-    #define ccrsa_ctx_n(_ctx_)         (ccrsa_ctx_zm(_ctx_).zp->n)
-#else
-    #define ccrsa_ctx_zm(_ctx_)        ((cczp_t)(_ctx_))
-    #define ccrsa_ctx_n(_ctx_)         (ccrsa_ctx_zm(_ctx_)->n)
-    #define ccrsa_ctx_m(_ctx_)         ((_ctx_)->pb_ccn)
-#endif
+#define ccrsa_ctx_zm(_ctx_)        ((cczp_t)(_ctx_))
+#define ccrsa_ctx_n(_ctx_)         (ccrsa_ctx_zm(_ctx_)->n)
+#define ccrsa_ctx_m(_ctx_)         ((_ctx_)->pb_ccn)
 
 #define ccrsa_ctx_e(_ctx_)         (ccrsa_ctx_m(_ctx_) + 2 * ccrsa_ctx_n(_ctx_) + 1)
 #define ccrsa_ctx_d(_ctx_)         (ccrsa_ctx_m(_ctx_) + 3 * ccrsa_ctx_n(_ctx_) + 1)
@@ -121,37 +79,14 @@ typedef struct ccrsa_pub_ctx ccrsa_pub_ctx;
 // accessors to ccrsa private key fields
 // The offsets are computed using pv_ccn. If any object other than ccrsa_priv_ctx_t
 // is passed to the macros, compiler error is generated.
-#if CORECRYPTO_USE_TRANSPARENT_UNION
-
-/* rvalue accessors to ccec_key fields. */
-CC_CONST CC_INLINE
-ccrsa_priv_ctx_t ccrsa_get_private_ctx_ptr(ccrsa_full_ctx_t fk) {
-    cc_unit *p = (cc_unit *)fk.full;
-    cc_size p_size = ccrsa_ctx_n(fk);
-    p += ccn_nof_size(ccrsa_pub_ctx_size(ccn_sizeof_n(p_size))) + p_size;
-    ccrsa_priv_ctx *priv = (ccrsa_priv_ctx *)p;
-    return (ccrsa_priv_ctx_t)priv;
-}
-
-CC_CONST CC_INLINE
-ccrsa_pub_ctx_t ccrsa_ctx_public(ccrsa_full_ctx_t fk) {
-    return (ccrsa_pub_ctx_t) fk.full;
-}
-
-#define ccrsa_ctx_private_zp(FK)   ((ccrsa_get_private_ctx_ptr(FK)).zp)
-#define ccrsa_ctx_private_zq(FK)   ((cczp_t)((ccrsa_get_private_ctx_ptr(FK)).zp.zp->ccn + 2 * ccrsa_ctx_private_zp(FK).zp->n + 1))
-#define ccrsa_ctx_private_dp(FK)   ((ccrsa_get_private_ctx_ptr(FK)).zp.zp->ccn + 4 * ccrsa_ctx_private_zp(FK).zp->n + 2 + ccn_nof_size(sizeof(struct cczp)))
-#define ccrsa_ctx_private_dq(FK)   ((ccrsa_get_private_ctx_ptr(FK)).zp.zp->ccn + 5 * ccrsa_ctx_private_zp(FK).zp->n + 2 + ccn_nof_size(sizeof(struct cczp)))
-#define ccrsa_ctx_private_qinv(FK) ((ccrsa_get_private_ctx_ptr(FK)).zp.zp->ccn + 6 * ccrsa_ctx_private_zp(FK).zp->n + 2 + ccn_nof_size(sizeof(struct cczp)))
-
-#else
 #define ccrsa_ctx_private_zp(FK)   ((cczp_t)ccrsa_get_private_ctx_ptr(FK))
 #define ccrsa_ctx_private_zq(FK)   ((cczp_t)((ccrsa_get_private_ctx_ptr(FK))->pv_ccn + 2 * ccrsa_ctx_private_zp(FK)->n + 1))
 #define ccrsa_ctx_private_dp(FK)   ((ccrsa_get_private_ctx_ptr(FK))->pv_ccn + 4 * ccrsa_ctx_private_zp(FK)->n + 2 + ccn_nof_size(sizeof(struct cczp)))
 #define ccrsa_ctx_private_dq(FK)   ((ccrsa_get_private_ctx_ptr(FK))->pv_ccn + 5 * ccrsa_ctx_private_zp(FK)->n + 2 + ccn_nof_size(sizeof(struct cczp)))
 #define ccrsa_ctx_private_qinv(FK) ((ccrsa_get_private_ctx_ptr(FK))->pv_ccn + 6 * ccrsa_ctx_private_zp(FK)->n + 2 + ccn_nof_size(sizeof(struct cczp)))
 
-CC_CONST CC_INLINE
+/* rvalue accessors to ccec_key fields. */
+CC_INLINE
 ccrsa_priv_ctx_t ccrsa_get_private_ctx_ptr(ccrsa_full_ctx_t fk) {
     ccrsa_priv_ctx_t priv = (ccrsa_priv_ctx_t)(ccrsa_ctx_d(fk)+ccrsa_ctx_n(fk));
     return priv;
@@ -163,118 +98,374 @@ ccrsa_priv_ctx_t ccrsa_get_private_ctx_ptr(ccrsa_full_ctx_t fk) {
  @param      fk      RSA full key
  @result     Returns RSA public ker
  */
-CC_CONST CC_INLINE
+CC_INLINE
 ccrsa_pub_ctx_t ccrsa_ctx_public(ccrsa_full_ctx_t fk) {
     return (ccrsa_pub_ctx_t) fk;
 }
 
-#endif
-
-/* Return exact key bit size */
-static inline size_t
-ccrsa_pubkeylength(ccrsa_pub_ctx_t pubk) {
-    return cczp_bitlen(ccrsa_ctx_zm(pubk));
-}
+/*!
+@function   ccrsa_pubkeylength
+@abstract   Compute the actual bit length of the RSA key (bit length of the modulus)
+@param      pubk  An initialized RSA public key
+@result     bit length of the RSA key
+*/
+CC_NONNULL_ALL
+size_t ccrsa_pubkeylength(ccrsa_pub_ctx_t pubk);
 
 /* PKCS1 pad_markers */
 #define CCRSA_PKCS1_PAD_SIGN     1
 #define CCRSA_PKCS1_PAD_ENCRYPT  2
 
-/* Initialize key based on modulus and e as cc_unit.  key->zp.n must already be set. */
-CC_NONNULL_TU((1)) CC_NONNULL((2, 3))
-void ccrsa_init_pub(ccrsa_pub_ctx_t key, const cc_unit *modulus,
-                    const cc_unit *e);
+/*!
+@function   ccrsa_init_pub
+@abstract   Initialize an RSA public key structure based on modulus and exponent. Values are copied into the structure.
+@param      pubk   allocated public key structure (see requirements below)
+@param      modulus  cc_unit array of the modulus
+@param      exponent  cc_unit array of the exponent
+@result     CCERR_OK if no error
+@discussion ccrsa_ctx_n(pubk) must have been initialized based on the modulus size, typically using ccn_nof_size(mod_nbytes).
+ The public key structure pubk is typically allocated with ccrsa_pub_ctx_decl(ccn_sizeof_size(mod_nbytes), pubk);
+*/
+CC_NONNULL_ALL
+int ccrsa_init_pub(ccrsa_pub_ctx_t pubk, const cc_unit *modulus,
+                    const cc_unit *exponent);
+
+/*! @function ccrsa_make_priv
+  @abstract   Initializes an RSA public and private key given the public
+              exponent e and prime factors p and q.
+
+  @param      full_ctx   Initialized context with ccrsa_ctx_n(full_ctx) set to 2*ccn_nof_size(p_nbytes)
+  @param      e_nbytes   Number of bytes of public exponent e.
+  @param      e_bytes    Public exponent e in Big Endian.
+  @param      p_nbytes   Number of bytes of prime factor p.
+  @param      p_bytes    Prime factor p in Big Endian.
+  @param      q_nbytes   Number of bytes of prime factor q.
+  @param      q_bytes    Prime factor q in Big Endian.
+
+  @return     0          iff successful.
+
+  @discussion  ccrsa_ctx_n(full_ctx) must already be set to 2*ccn_nof_size(p_mbytes), with the expectation that p_nbytes>q_nbytes.
+  e is the public exponent, and e_nbytes<= 2*p_nbytes.
+  The output is a fully formed RSA context with N=pq, d=e^{-1} mod lambda(N), and appropriate inverses of different associated values precomputed
+  to speed computation.
+*/
+int ccrsa_make_priv(ccrsa_full_ctx_t full_ctx,
+                    size_t e_nbytes, const uint8_t *e_bytes,
+                    size_t p_nbytes, const uint8_t *p_bytes,
+                    size_t q_nbytes, const uint8_t *q_bytes);
+
+/*! @function ccrsa_recover_priv
+  @abstract   Initializes an RSA public and private key given the modulus m,
+              the public exponent e and the private exponent d.
+
+  @discussion Follows the algorithm described by
+              NIST SP 800-56B, Appendix C, "Prime Factory Recovery".
+
+  @param      full_ctx   Initialized context with ccrsa_ctx_n(full_ctx) set to ccn_nof_size(m_nbytes)
+  @param      m_nbytes   Number of bytes of modulus m.
+  @param      m_bytes    Modulus m in Big Endian.
+  @param      e_nbytes   Number of bytes of public exponent e.
+  @param      e_bytes    Public exponent e in Big Endian.
+  @param      d_nbytes   Number of bytes of private exponent d.
+  @param      d_bytes    Private exponent d in Big Endian.
+  @param      rng        RNG instance.
+
+  @return     0          iff successful.
+*/
+int ccrsa_recover_priv(ccrsa_full_ctx_t full_ctx,
+                       size_t m_nbytes, const uint8_t *m_bytes,
+                       size_t e_nbytes, const uint8_t *e_bytes,
+                       size_t d_nbytes, const uint8_t *d_bytes,
+                       struct ccrng_state *rng);
+
+/*!
+@function   ccrsa_make_pub
+@abstract   Initialize public key based on modulus and public exponent  as big endian byte arrays;
+
+@param      pubk   allocated public key structure (see requirements below)
+@param      exp_nbytes Number of bytes in big endian exponent.
+@param      exp     Pointer to big endian exponent e (may have leading 0's).
+@param      mod_nbytes  Number of bytes in big endian modulus.
+@param      mod     Pointer to big endian to rsa modulus  N.
+@result     0    iff successful.
 
-/* Initialize key based on modulus and e as big endian byte array
-    key->zp.n must already be set. */
-CC_NONNULL_TU((1)) CC_NONNULL((3 ,5))
+@discussion ccrsa_ctx_n(pubk) must have been initialized based on the modulus size, typically using ccn_nof_size(mod_nbytes).
+    The public key structure pubk is typically allocated with ccrsa_pub_ctx_decl(ccn_sizeof_size(mod_nbytes), pubk);
+*/
+
+CC_NONNULL((1, 3, 5))
 int ccrsa_make_pub(ccrsa_pub_ctx_t pubk,
-                              size_t exp_nbytes, const uint8_t *exp,
-                              size_t mod_nbytes, const uint8_t *mod);
-
-/* Do a public key crypto operation (typically verify or encrypt) on in and put
-   the result in out. Both in and out should be cc_unit aligned and
-   ccrsa_key_n(key) units long. Clients should use ccn_read_uint() to
-   convert bytes to a cc_unit to use for this API.*/
-CC_NONNULL_TU((1)) CC_NONNULL((2, 3))
+                   size_t exp_nbytes, const uint8_t *exp,
+                   size_t mod_nbytes, const uint8_t *mod);
+
+/*!
+@function   ccrsa_pub_crypt
+@abstract   Perform an RSA public key operation: (in)^e mod m
+@param      key   initialized public key defining e and m
+@param      out   result of the operation, at least ccrsa_key_n(key) cc_units must have been allocated
+@param      in     base of the exponentiation, of size ccrsa_key_n(key)
+@result     CCERR_OK if no error
+@discussion Input to this function must not be secrets as the execution flow may expose their values
+        Clients can use ccn_read_uint() to convert bytes to cc_units to use for this API.
+*/
+CC_NONNULL((1, 2, 3))
 int ccrsa_pub_crypt(ccrsa_pub_ctx_t key, cc_unit *out, const cc_unit *in);
 
-/* Generate an nbit rsa key pair in key, which should be allocated using
-   ccrsa_full_ctx_decl(ccn_sizeof(1024), rsa_ctx). The unsigned big endian
-   byte array exponent e of length e_size is used as the exponent. It's an
-   error to call this function with an exponent larger than nbits. rng
-   must be a pointer to an initialized struct ccrng_state. */
-CC_NONNULL_TU((2)) CC_NONNULL((4, 5))
-int ccrsa_generate_key(size_t nbits, ccrsa_full_ctx_t rsa_ctx,
-                       size_t e_size, const void *e, struct ccrng_state *rng) CC_WARN_RESULT;
-
-/* Generate RSA key in conformance with FIPS186-4 standard */
-CC_NONNULL_TU((2)) CC_NONNULL((4, 5, 6))
-int
+/*!
+@function   ccrsa_generate_key
+@abstract   Generate a nbit RSA key pair.
+
+@param      nbits      Bit size requested for the key
+@param      fk         Allocated context where the generated key will be stored
+@param      e_nbytes   Byte size of the input public exponent
+@param      e_bytes    Input public exponent in big endian. Recommend value is {0x01, 0x00, 0x01}
+@param      rng        Random Number generator used.
+@result     CCERR_OK if no error
+
+@discussion
+    fk should be allocated using ccrsa_full_ctx_decl(ccn_sizeof(nbits), fk).
+    The unsigned big endian byte array exponent e of length e_size is used as the exponent. It's an error to call this function with an exponent larger than nbits
+*/
+CC_NONNULL_ALL
+int ccrsa_generate_key(size_t nbits, ccrsa_full_ctx_t fk,
+                       size_t e_nbytes, const void *e_bytes, struct ccrng_state *rng) CC_WARN_RESULT;
+
+/*!
+@function   ccrsa_generate_fips186_key
+@abstract   Generate a nbit RSA key pair in conformance with FIPS186-4 standard.
+
+@param      nbits      Bit size requested for the key
+@param      fk         Allocated context where the generated key will be stored
+@param      e_nbytes   Byte size of the input public exponent
+@param      e_bytes    Input public exponent in big endian. Recommend value is {0x01, 0x00, 0x01}
+@param      rng        Random Number generator used for p and q
+@param      rng_mr     Random Number generator only used for the primality check
+@result     CCERR_OK if no error
+
+@discussion
+   fk should be allocated using ccrsa_full_ctx_decl(ccn_sizeof(nbits), fk).
+   rng and rng_mr shoud be set to the same value. The distinction is only relevant for testing
+*/
+CC_NONNULL_ALL int
 ccrsa_generate_fips186_key(size_t nbits, ccrsa_full_ctx_t fk,
-                           size_t e_size, const void *eBytes,
-                           struct ccrng_state *rng1, struct ccrng_state *rng2) CC_WARN_RESULT;
+                           size_t e_nbytes, const void *e_bytes,
+                           struct ccrng_state *rng, struct ccrng_state *rng_mr) CC_WARN_RESULT;
+
+
 
 /* Construct RSA key from fix input in conformance with FIPS186-4 standard */
-CC_NONNULL_TU((16)) CC_NONNULL((3, 5, 7, 9, 11, 13, 15))
+
+/*!
+@function   ccrsa_make_fips186_key
+@abstract   Initialize an RSA full key from explicit inputs necessary for validating conformance to FIPS186-4
+
+@param      nbits size in bits of the key to construct
+@param      e_n Size in cc_unit of the public exponent
+@param      e      Public exponent  represented in cc_units
+@param      xp1_nbytes   Size in byte of the first seed for the construction of p
+@param      xp1 First seed for the construction of p
+@param      xp2_nbytes   Size in byte of the second seed for the construction of p
+@param      xp2 Second seed for the construction of p
+@param      xp_nbytes   Size in byte of the large seed for the construction of p
+@param      xp large seed for the construction of p
+@param      xq1_nbytes   Size in byte of the first seed for the construction of q
+@param      xq1 First seed for the construction of q
+@param      xq2_nbytes   Size in byte of the second seed for the construction of q
+@param      xq2 Second seed for the construction of q
+@param      xq_nbytes   Size in byte of the large seed for the construction of q
+@param      xq large seed for the construction of q
+@param      fk     Allocated context where the output constructed key is stored
+@param      np     Pointer to the size in cc_unit of the buffer for the output prime factor p. Updated with actual size.
+@param      r_p   Copy of the output prime factor p
+@param      nq     Pointer to the size in cc_unit of the buffer for the output prime factor q. Updated with actual size.
+@param      r_q   Copy of the output prime factor q
+@param      nm     Pointer to the size in cc_unit of the buffer for the output modulus m=p*q. Updated with actual size.
+@param      r_m   Copy of the output modulus m=p*q
+@param      nd     Pointer to the size in cc_unit of the buffer for the output private exponent d. Updated with actual size.
+@param      r_d   Copy of the output private exponent d
+@result     0          iff successful.
+ @discussion
+    fk should be allocated using ccrsa_full_ctx_decl(ccn_sizeof(nbits), fk).
+*/
+
+CC_NONNULL((3, 5, 7, 9, 11, 13, 15, 16))
 int
 ccrsa_make_fips186_key(size_t nbits,
                        const cc_size e_n, const cc_unit *e,
-                       const cc_size xp1Len, const cc_unit *xp1, const cc_size xp2Len, const cc_unit *xp2,
-                       const cc_size xpLen, const cc_unit *xp,
-                       const cc_size xq1Len, const cc_unit *xq1, const cc_size xq2Len, const cc_unit *xq2,
-                       const cc_size xqLen, const cc_unit *xq,
+                       const cc_size xp1_nbytes, const cc_unit *xp1, const cc_size xp2_nbytes, const cc_unit *xp2,
+                       const cc_size xp_nbytes, const cc_unit *xp,
+                       const cc_size xq1_nbytes, const cc_unit *xq1, const cc_size xq2_nbytes, const cc_unit *xq2,
+                       const cc_size xq_nbytes, const cc_unit *xq,
                        ccrsa_full_ctx_t fk,
                        cc_size *np, cc_unit *r_p,
                        cc_size *nq, cc_unit *r_q,
                        cc_size *nm, cc_unit *r_m,
                        cc_size *nd, cc_unit *r_d);
 
+/*
+ Signing and Verification algorithms
+*/
+
 /*!
- * @brief ccrsa_sign_pss() generates RSASSA-PSS signature in PKCS1-V2 format
- *
- * note that in RSASSA-PSS, salt length is part of the signature as specified in ASN1
- * RSASSA-PSS-params ::= SEQUENCE {
- * hashAlgorithm      [0] HashAlgorithm      DEFAULT sha1,
- * maskGenAlgorithm   [1] MaskGenAlgorithm   DEFAULT mgf1SHA1,
- * saltLength         [2] INTEGER            DEFAULT 20,
- * trailerField       [3] TrailerField       DEFAULT trailerFieldBC
- *
- *
- * FIPS 186-4 for RSASSA-PSS:
- * .... Both signature schemes are approved for use, but additional constraints are imposed beyond those specified in PKCS #1 v2.1.....
- *
- * • If nlen = 1024 bits (i.e., 128 bytes), and the output length of the approved hash function output block is 512 bits (i.e., 64 bytes), then the length (in bytes) of the salt (sLen) shall satisfy 0 ≤ sLen ≤ hLen – 2,
- * • Otherwise, the length (in bytes) of the salt (sLen) shall satisfy 0 ≤ sLen ≤ hLen, where hLen is the length of the hash function output block (in bytes).
- *
- *
- * • CAVS test vectors are not very useful in the case of RSA-PSS, because they only validate the exponentiation part of the signature. See: http://csrc.nist.gov/groups/STM/cavp/documents/components/RSA2SP1VS.pdf
- *
- * @param      key              The RSA key
- * @param      hashAlgorithm    The hash algorithm used to generate mHash from the original message. It is also used inside the PSS encoding function. This is also the hash function to be used in the mask generation function (MGF)
- * @param   MgfHashAlgorithm The hash algorithm for thr mask generation function
- * @param   rng              Random number geberator to generate salt in PSS encoding
- * @param      saltSize          Intended length of the salt
- * @param   hSize             Length of message hash . Must be equal to hashAlgorithm->output_size
- * @param      mHash            The input that needs to be signed. This is the hash of message M with length of hLen
- *
- * @param   sig              The signature output
- * @param   sigSize           The length of generated signature in bytes, which equals the size of the RSA modulus.
- * @return                   0:ok, non-zero:error
+@function ccrsa_sign_pss
+
+@brief  ccrsa_sign_pss() generates RSASSA-PSS signature in PKCS1-V2 format given an input digest
+
+@param  key               The RSA key
+@param  hashAlgorithm    The hash algorithm used to generate mHash from the original message. It is also used inside the PSS encoding function.
+@param  MgfHashAlgorithm The hash algorithm for thr mask generation function
+@param  rng              Random number geberator to generate salt in PSS encoding
+@param  salt_nbytes     Intended length of the salt
+@param  digest_nbytes   Length of message hash . Must be equal to hashAlgorithm->output_size
+@param  digest           The input that needs to be signed. This is the hash of message M with length of hLen
+@param  sig_nbytes       The length of generated signature in bytes, which equals the size of the RSA modulus.
+@param  sig               The signature output
+@return 0:ok, non-zero:error
+@discussion
+  note that in RSASSA-PSS, salt length is part of the signature as specified in ASN1
+  RSASSA-PSS-params ::= SEQUENCE {
+  hashAlgorithm      [0] HashAlgorithm      DEFAULT sha1,
+  maskGenAlgorithm   [1] MaskGenAlgorithm   DEFAULT mgf1SHA1,
+  saltLength         [2] INTEGER            DEFAULT 20,
+  trailerField       [3] TrailerField       DEFAULT trailerFieldBC
+  • If nlen = 1024 bits (i.e., 128 bytes), and the output length of the approved hash function output block is 512 bits (i.e., 64 bytes), then the length (in bytes) of the salt (sLen) shall satisfy 0 ≤ sLen ≤ hLen – 2,
+  • Otherwise, the length (in bytes) of the salt (sLen) shall satisfy 0 ≤ sLen ≤ hLen, where hLen is the length of the hash function output block (in bytes).
  */
-CC_NONNULL((2,3,5,7,8,9))
+CC_NONNULL((1, 2, 3, 5, 7, 8, 9))
 int ccrsa_sign_pss(ccrsa_full_ctx_t key,
                    const struct ccdigest_info* hashAlgorithm, const struct ccdigest_info* MgfHashAlgorithm,
-                   size_t saltSize, struct ccrng_state *rng,
-                   size_t hSize, const uint8_t *mHash,
-                   size_t *sigSize, uint8_t *sig);
+                   size_t salt_nbytes, struct ccrng_state *rng,
+                   size_t digest_nbytes, const uint8_t *digest,
+                   size_t *sig_nbytes, uint8_t *sig);
+
+/*!
+@function ccrsa_sign_pss_msg
+
+@brief  ccrsa_sign_pss_msg() generates a RSASSA-PSS signature in PKCS1-V2 format given an input message
+
+@param  key               The RSA key
+@param  hashAlgorithm     The hash algorithm used to generate mHash from the input message. It is also used inside the PSS encoding function.
+@param  MgfHashAlgorithm  The hash algorithm for thr mask generation function
+@param  rng               Random number generator to generate salt in PSS encoding
+@param  salt_nbytes       Intended length of the salt
+@param  msg_nbytes        Length of message.
+@param  msg               The input that needs to be signed. This will be hashed using `hashAlgorithm`
+@param  sig_nbytes        The length of generated signature in bytes, which equals the size of the RSA modulus.
+@param  sig               The signature output
+@return 0:ok, non-zero:error
+@discussion
+  note that in RSASSA-PSS, salt length is part of the signature as specified in ASN1
+  RSASSA-PSS-params ::= SEQUENCE {
+  hashAlgorithm      [0] HashAlgorithm      DEFAULT sha1,
+  maskGenAlgorithm   [1] MaskGenAlgorithm   DEFAULT mgf1SHA1,
+  saltLength         [2] INTEGER            DEFAULT 20,
+  trailerField       [3] TrailerField       DEFAULT trailerFieldBC
+  • If nlen = 1024 bits (i.e., 128 bytes), and the output length of the approved hash function output block is 512 bits (i.e., 64 bytes), then the length (in bytes) of the salt (sLen) shall satisfy 0 ≤ sLen ≤ hLen – 2,
+  • Otherwise, the length (in bytes) of the salt (sLen) shall satisfy 0 ≤ sLen ≤ hLen, where hLen is the length of the hash function output block (in bytes).
+ */
+CC_NONNULL((1, 2, 3, 5, 7, 8, 9))
+int ccrsa_sign_pss_msg(ccrsa_full_ctx_t key,
+                   const struct ccdigest_info* hashAlgorithm, const struct ccdigest_info* MgfHashAlgorithm,
+                   size_t salt_nbytes, struct ccrng_state *rng,
+                   size_t msg_nbytes, const uint8_t *msg,
+                   size_t *sig_nbytes, uint8_t *sig);
 
-CC_NONNULL((2,3,5,7,9))
+/*!
+@function   ccrsa_verify_pss
+@brief ccrsa_verify_pss() verifies RSASSA-PSS signature in PKCS1-V2 format
+
+@param   key                The RSA public key
+@param   hashAlgorithm      The hash algorithm used to generate mHash from the original message. It is also used inside the PSS encoding function.
+@param   MgfHashAlgorithm   The hash algorithm for the mask generation function
+@param   digest_nbytes      Length of message hash . Must be equal to hashAlgorithm->output_size
+@param   digest             The signed message hash
+@param   sig_nbytes         The length of generated signature in bytes, which equals the size of the RSA modulus.
+@param   sig                The signature to verify
+@param   salt_nbytes        Length of the salt as used during signature generation. Mismatch would result in the signature being considered invalid
+@param   valid              Input boolean used to indicate a valid signature.
+
+@result  0 && valid == True indicates a valid signature. If return != 0 or valid == False, the signature is invalid.
+*/
+
+CC_NONNULL((2, 3, 5, 7, 9))
 int ccrsa_verify_pss(ccrsa_pub_ctx_t key,
-                     const struct ccdigest_info* di, const struct ccdigest_info* MgfDi,
-                     size_t digestSize, const uint8_t *digest,
-                     size_t sigSize, const uint8_t *sig,
-                     size_t saltSize, bool *valid);
+                     const struct ccdigest_info* hashAlgorithm,
+                     const struct ccdigest_info* MgfHashAlgorithm,
+                     size_t digest_nbytes, const uint8_t *digest,
+                     size_t sig_nbytes, const uint8_t *sig,
+                     size_t salt_nbytes, bool *valid)
+cc_deprecate_with_replacement("ccrsa_verify_pss_digest", 13.0, 10.15, 13.0, 6.0, 4.0);
+
+/*!
+@function   ccrsa_verify_pss_digest
+@brief ccrsa_verify_pss_digest() verifies RSASSA-PSS signature in PKCS1-V2 format, given the digest
+
+@param   key               The RSA public key
+@param   di                The hash algorithm used to generate the hash of the message.
+@param   mgfdi             The hash algorithm for the mask generation function
+@param   digest_nbytes     Length of digest. Must be equal to di->output_size
+@param   digest            The signed message hash
+@param   sig_nbytes        The length of generated signature in bytes, which equals the size of the RSA modulus.
+@param   sig               The signature to verify
+@param   salt_nbytes       Length of the salt as used during signature generation.
+@param   fault_canary_out  OPTIONAL cc_fault_canary_t (see discussion)
+
+@result   CCERR_SIGNATURE_VALID on signature success.
+         CCERR_SIGNATURE_INVALID on signature failure.
+         other on some other signature verification issue.
+@discussion If the fault_canary_out argument is not NULL, the value `CCRSA_PSS_FAULT_CANARY` will be placed into fault_canary_out
+ if the salted input hash is equal to the decoded hash (which strongly implies the signature is valid). Callers can then securely compare this output buffer against CCRSA_PSS_FAULT_CANARY, using CC_FAULT_CANARY_EQUAL, as an additional check of signature validity: if the two canary values are equal, the signature is valid otherwise it is not. If the signature is valid and the canary values are NOT equal this may indicate a potentially injected computational fault.
+*/
+
+CC_NONNULL((1, 2, 3, 5, 7))
+int ccrsa_verify_pss_digest(ccrsa_pub_ctx_t key,
+                            const struct ccdigest_info* di,
+                            const struct ccdigest_info* mgfdi,
+                            size_t digest_nbytes, const uint8_t *digest,
+                            size_t sig_nbytes, const uint8_t *sig,
+                            size_t salt_nbytes, cc_fault_canary_t fault_canary_out);
+
+/*!
+@function   ccrsa_verify_pss_msg
+@brief ccrsa_verify_pss_msg() verifies RSASSA-PSS signature in PKCS1-V2 format, given the message
+
+@param   key               The RSA public key
+@param   di                The hash algorithm used to generate the hash of the message.
+@param   mgfdi             The hash algorithm for the mask generation function
+@param   msg_nbytes        Length of message
+@param   msg               The signed message
+@param   sig_nbytes        The length of generated signature in bytes, which equals the size of the RSA modulus.
+@param   sig               The signature to verify
+@param   salt_nbytes       Length of the salt as used during signature generation.
+@param   fault_canary_out  OPTIONAL cc_fault_canary_t (see discussion)
+
+@result  CCERR_SIGNATURE_VALID on signature success.
+        CCERR_SIGNATURE_INVALID on signature failure.
+        other on some other signature verification issue.
+@discussion If the fault_canary_out argument is not NULL, the value `CCRSA_PSS_FAULT_CANARY` will be placed into fault_canary_out
+if the salted input hash is equal to the decoded hash (which strongly implies the signature is valid). Callers can then securely compare this output buffer against CCRSA_PSS_FAULT_CANARY, using CC_FAULT_CANARY_EQUAL, as an additional check of signature validity: if the two canary values are equal, the signature is valid otherwise it is not. If the signature is valid and the canary values are NOT equal this may indicate a potentially injected computational fault.
+*/
+
+CC_NONNULL((1, 2, 3, 5, 7))
+int ccrsa_verify_pss_msg(ccrsa_pub_ctx_t key,
+                         const struct ccdigest_info* di,
+                         const struct ccdigest_info* mgfdi,
+                         size_t msg_nbytes, const uint8_t *msg,
+                         size_t sig_nbytes, const uint8_t *sig,
+                         size_t salt_nbytes, cc_fault_canary_t fault_canary_out);
+
 
 /*!
  @function   ccrsa_sign_pkcs1v15
@@ -284,48 +475,125 @@ int ccrsa_verify_pss(ccrsa_pub_ctx_t key,
  @param      oid        OID describing the type of digest passed in
  @param      digest_len Byte length of the digest
  @param      digest     Byte array of digest_len bytes containing the digest
- @param      sig_len    Pointer to the number of byte allocate for sig.
+ @param      sig_len    Pointer to the number of bytes allocated for sig.
                         Output the exact size of the signature.
  @param      sig        Pointer to the allocated buffer of size *sig_len
                         for the output signature
 
- @result     0 iff successful.
+ @result     CCERR_OK iff successful.
  
   @discussion Null OID is a special case, required to support RFC 4346 where the padding
  is based on SHA1+MD5. In general it is not recommended to use a NULL OID,
  except when strictly required for interoperability
 
  */
-CC_NONNULL_TU((1)) CC_NONNULL((4, 5, 6))
+CC_NONNULL((1, 4, 5, 6))
 int ccrsa_sign_pkcs1v15(ccrsa_full_ctx_t key, const uint8_t *oid,
                         size_t digest_len, const uint8_t *digest,
                         size_t *sig_len, uint8_t *sig);
 
-
 /*!
- @function   ccrsa_sign_pkcs1v15
+ @function   ccrsa_sign_pkcs1v15_msg
  @abstract   RSA signature with PKCS#1 v1.5 format per PKCS#1 v2.2
 
- @param      key        Public key
- @param      oid        OID describing the type of digest passed in
- @param      digest_len Byte length of the digest
- @param      digest     Byte array of digest_len bytes containing the digest
- @param      sig_len    Number of byte of the signature sig.
- @param      sig        Pointer to the signature buffer of sig_len
- @param      valid      Output boolean, true if the signature is valid.
+ @param      key       Full key
+ @param      di        Digest context
+ @param      msg_len   Byte length of the message to sign
+ @param      msg       Byte array of msg_len bytes containing the message. Will be hashed with di.
+ @param      sig_len   Pointer to the number of bytes allocated for sig.
+                       Output the exact size of the signature.
+ @param      sig       Pointer to the allocated buffer of size *sig_len
+                       for the output signature
 
- @result     0 iff successful.
+ @result     CCERR_OK iff successful.
  
-  @discussion Null OID is a special case, required to support RFC 4346 where the padding
- is based on SHA1+MD5. In general it is not recommended to use a NULL OID, 
- except when strictly required for interoperability
+ @discussion Null OID is not supported by this API.
+
  */
-CC_NONNULL_TU((1)) CC_NONNULL((4, 6, 7))
+CC_NONNULL((1, 2, 4, 5, 6))
+int ccrsa_sign_pkcs1v15_msg(ccrsa_full_ctx_t key, const struct ccdigest_info* di,
+                            size_t msg_len, const uint8_t *msg,
+                            size_t *sig_len, uint8_t *sig);
+
+
+/*!
+  @function   ccrsa_verify_pkcs1v15
+  @abstract   RSA signature with PKCS#1 v1.5 format per PKCS#1 v2.2
+
+  @param      key        Public key
+  @param      oid        OID describing the type of digest passed in
+  @param      digest_len Byte length of the digest
+  @param      digest     Byte array of digest_len bytes containing the digest
+  @param      sig_len    Number of bytes of the signature sig.
+  @param      sig        Pointer to the signature buffer of sig_len
+  @param      valid      Output boolean, true if the signature is valid.
+
+  @result     A return value of 0 and valid = True indicates a valid signature.
+              A non-zero return value or valid = False indicates an invalid signature.
+
+  @discussion Null OID is a special case, required to support RFC 4346
+  where the padding is based on SHA1+MD5. In general it is not
+  recommended to use a NULL OID, except when strictly required for
+  interoperability.
+*/
+CC_NONNULL((1, 4, 6, 7))
 int ccrsa_verify_pkcs1v15(ccrsa_pub_ctx_t key, const uint8_t *oid,
                           size_t digest_len, const uint8_t *digest,
                           size_t sig_len, const uint8_t *sig,
                           bool *valid);
 
+/*!
+  @function   ccrsa_verify_pkcs1v15_digest
+  @abstract   RSA signature with PKCS#1 v1.5 format per PKCS#1 v2.2, given a digest
+
+  @param      key                 Public key
+  @param      oid                 OID describing the type of digest passed in
+  @param      digest_len          Byte length of the digest
+  @param      digest              Byte array of digest_len bytes containing the digest
+  @param      sig_len             Number of bytes of the signature sig.
+  @param      sig                 Pointer to the signature buffer of sig_len
+  @param      fault_canary_out    OPTIONAL cc_fault_canary_t
+
+  @result      CCERR_VALID_SIGNATURE if a valid signature.
+              CCERR_INVALID_SIGNATURE if an invalid signature.
+              Other if the verification procedure failed.
+ @discussion If the fault_canary_out argument is not NULL, the value `CCRSA_PKCS1_FAULT_CANARY` will be placed into fault_canary_out
+ if the input hash is equal to the decoded hash (which strongly implies the signature is valid). Callers can then securely compare this output buffer against CCRSA_PKCS1_FAULT_CANARY, using CC_FAULT_CANARY_EQUAL, as an additional check of signature validity: if the two canary values are equal, the signature is valid otherwise it is not. If the signature is valid and the canary values are NOT equal this may indicate a potentially injected computational fault.
+*/
+CC_NONNULL((1, 4, 6))
+int ccrsa_verify_pkcs1v15_digest(ccrsa_pub_ctx_t key, const uint8_t *oid,
+                          size_t digest_len, const uint8_t *digest,
+                          size_t sig_len, const uint8_t *sig,
+                          cc_fault_canary_t fault_canary_out);
+
+/*!
+  @function   ccrsa_verify_pkcs1v15_msg
+  @abstract   RSA signature with PKCS#1 v1.5 format per PKCS#1 v2.2
+
+  @param      key                Public key
+  @param      di                 Hash function
+  @param      msg_len            Byte length of the digest
+  @param      msg                Byte array of digest_len bytes containing the digest
+  @param      sig_len            Number of bytes of the signature sig.
+  @param      sig                Pointer to the signature buffer of sig_len
+  @param      fault_canary_out   OPTIONAL cc_fault_canary_t
+
+  @result     CCERR_VALID_SIGNATURE if a valid signature.
+             CCERR_INVALID_SIGNATURE if an invalid signature.
+             Other if the verification procedure failed.
+
+  @discussion Null OID is not supported by this API.
+             If the fault_canary_out argument is not NULL, the value `CCRSA_PKCS1_FAULT_CANARY` will
+             be placed into fault_canary_out if the input hash is equal to the decoded hash (which strongly
+             implies the signature is valid). Callers can then securely compare this output buffer against CCRSA_PKCS1_FAULT_CANARY, using CC_FAULT_CANARY_EQUAL, as an additional check of signature validity: if the two canary values are equal, the signature is valid otherwise it is not. If the signature is valid and the canary values are NOT equal this may indicate a potentially injected computational fault.
+*/
+CC_NONNULL((1, 2, 4, 6))
+int ccrsa_verify_pkcs1v15_msg(ccrsa_pub_ctx_t key, const struct ccdigest_info* di,
+                          size_t msg_len, const uint8_t *msg,
+                          size_t sig_len, const uint8_t *sig,
+                          cc_fault_canary_t fault_canary_out);
+
 /*!
  @function   ccder_encode_rsa_pub_size
  @abstract   Calculate size of public key export format data package.
@@ -335,7 +603,7 @@ int ccrsa_verify_pkcs1v15(ccrsa_pub_ctx_t key, const uint8_t *oid,
  @result     Returns size required for encoding.
  */
 
-CC_NONNULL_TU((1))
+CC_NONNULL((1))
 size_t ccder_encode_rsa_pub_size(const ccrsa_pub_ctx_t key);
 
 /*!
@@ -347,7 +615,7 @@ size_t ccder_encode_rsa_pub_size(const ccrsa_pub_ctx_t key);
  @param      der_end    End of output DER buffer
  */
 
-CC_NONNULL_TU((1)) CC_NONNULL((2)) CC_NONNULL((3))
+CC_NONNULL((1, 2, 3))
 uint8_t *ccder_encode_rsa_pub(const ccrsa_pub_ctx_t key, uint8_t *der, uint8_t *der_end);
 
 
@@ -360,7 +628,7 @@ uint8_t *ccder_encode_rsa_pub(const ccrsa_pub_ctx_t key, uint8_t *der, uint8_t *
  @result     Returns size required for encoding.
  */
 
-CC_NONNULL_TU((1))
+CC_NONNULL((1))
 size_t ccder_encode_rsa_priv_size(const ccrsa_full_ctx_t key);
 
 /*!
@@ -372,7 +640,7 @@ size_t ccder_encode_rsa_priv_size(const ccrsa_full_ctx_t key);
  @param      der_end    End of output DER buffer
  */
 
-CC_NONNULL_TU((1)) CC_NONNULL((2)) CC_NONNULL((3))
+CC_NONNULL((1, 2, 3))
 uint8_t *ccder_encode_rsa_priv(const ccrsa_full_ctx_t key, const uint8_t *der, uint8_t *der_end);
 
 /*!
@@ -387,7 +655,7 @@ uint8_t *ccder_encode_rsa_priv(const ccrsa_full_ctx_t key, const uint8_t *der, u
  to declare the key itself.
  */
 
-CC_NONNULL((1)) CC_NONNULL((2))
+CC_NONNULL((12))
 cc_size ccder_decode_rsa_pub_n(const uint8_t *der, const uint8_t *der_end);
 
 /*!
@@ -402,7 +670,7 @@ cc_size ccder_decode_rsa_pub_n(const uint8_t *der, const uint8_t *der_end);
  @result     Key is initialized using the data in the public key message.
  */
 
-CC_NONNULL_TU((1)) CC_NONNULL((2)) CC_NONNULL((3))
+CC_NONNULL((1, 2, 3))
 const uint8_t *ccder_decode_rsa_pub(const ccrsa_pub_ctx_t key, const uint8_t *der, const uint8_t *der_end);
 
 /*!
@@ -416,7 +684,7 @@ const uint8_t *ccder_decode_rsa_pub(const ccrsa_pub_ctx_t key, const uint8_t *de
  to declare the key itself.
  */
 
-CC_NONNULL((1)) CC_NONNULL((2))
+CC_NONNULL((12))
 cc_size ccder_decode_rsa_pub_x509_n(const uint8_t *der, const uint8_t *der_end);
 
 /*!
@@ -430,7 +698,7 @@ cc_size ccder_decode_rsa_pub_x509_n(const uint8_t *der, const uint8_t *der_end);
  @result     Key is initialized using the data in the public key message.
  */
 
-CC_NONNULL_TU((1)) CC_NONNULL((2)) CC_NONNULL((3))
+CC_NONNULL((1, 2, 3))
 const uint8_t *ccder_decode_rsa_pub_x509(const ccrsa_pub_ctx_t key, const uint8_t *der, const uint8_t *der_end);
 
 
@@ -445,7 +713,7 @@ const uint8_t *ccder_decode_rsa_pub_x509(const ccrsa_pub_ctx_t key, const uint8_
  to declare the key itself.
  */
 
-CC_NONNULL((1)) CC_NONNULL((2))
+CC_NONNULL((12))
 cc_size ccder_decode_rsa_priv_n(const uint8_t *der, const uint8_t *der_end);
 
 /*!
@@ -459,7 +727,7 @@ cc_size ccder_decode_rsa_priv_n(const uint8_t *der, const uint8_t *der_end);
  @result     Key is initialized using the data in the public key message.
  */
 
-CC_NONNULL_TU((1)) CC_NONNULL((2)) CC_NONNULL((3))
+CC_NONNULL((1, 2, 3))
 const uint8_t *ccder_decode_rsa_priv(const ccrsa_full_ctx_t key, const uint8_t *der, const uint8_t *der_end);
 
 /*!
@@ -471,7 +739,7 @@ const uint8_t *ccder_decode_rsa_priv(const ccrsa_full_ctx_t key, const uint8_t *
  @result     Returns size required for encoding.
  */
 
-CC_CONST CC_INLINE CC_NONNULL_TU((1))
+CC_INLINE CC_NONNULL((1))
 size_t ccrsa_export_pub_size(const ccrsa_pub_ctx_t key) {
     return ccder_encode_rsa_pub_size(key);
 }
@@ -485,7 +753,7 @@ size_t ccrsa_export_pub_size(const ccrsa_pub_ctx_t key) {
  @param      out        Output buffer
  */
 
-CC_NONNULL_TU((1)) CC_NONNULL((3))
+CC_NONNULL((1, 3))
 int ccrsa_export_pub(const ccrsa_pub_ctx_t key, size_t out_len, uint8_t *out);
 /*!
  @function   ccrsa_import_pub_n
@@ -498,7 +766,7 @@ int ccrsa_export_pub(const ccrsa_pub_ctx_t key, size_t out_len, uint8_t *out);
  to declare the key itself.
  */
 
-CC_CONST CC_INLINE CC_NONNULL((2))
+CC_INLINE CC_NONNULL((2))
 cc_size ccrsa_import_pub_n(size_t inlen, const uint8_t *der) {
     cc_size size = ccder_decode_rsa_pub_x509_n(der, der + inlen);
     if(size == 0) {
@@ -518,7 +786,7 @@ cc_size ccrsa_import_pub_n(size_t inlen, const uint8_t *der) {
  @result     Key is initialized using the data in the public key message.
  */
 
-CC_NONNULL_TU((1)) CC_NONNULL((3))
+CC_NONNULL((1, 3))
 int ccrsa_import_pub(ccrsa_pub_ctx_t key, size_t inlen, const uint8_t *der);
 
 /*!
@@ -530,7 +798,7 @@ int ccrsa_import_pub(ccrsa_pub_ctx_t key, size_t inlen, const uint8_t *der);
  @result     Returns size required for encoding.
  */
 
-CC_CONST CC_INLINE CC_NONNULL_TU((1))
+CC_INLINE CC_NONNULL((1))
 size_t ccrsa_export_priv_size(const ccrsa_full_ctx_t key) {
     return ccder_encode_rsa_priv_size(key);
 }
@@ -544,7 +812,7 @@ size_t ccrsa_export_priv_size(const ccrsa_full_ctx_t key) {
  @param      out        Output buffer
  */
 
-CC_CONST CC_INLINE CC_NONNULL_TU((1)) CC_NONNULL((3))
+CC_INLINE CC_NONNULL((1, 3))
 int ccrsa_export_priv(const ccrsa_full_ctx_t key, size_t out_len, uint8_t *out) {
     return (ccder_encode_rsa_priv(key, out, out+out_len) != out);
 }
@@ -560,7 +828,7 @@ int ccrsa_export_priv(const ccrsa_full_ctx_t key, size_t out_len, uint8_t *out)
  to declare the key itself.
  */
 
-CC_CONST CC_INLINE CC_NONNULL((2))
+CC_INLINE CC_NONNULL((2))
 cc_size ccrsa_import_priv_n(size_t inlen, const uint8_t *der) {
     return ccder_decode_rsa_priv_n(der, der + inlen);
 }
@@ -576,16 +844,47 @@ cc_size ccrsa_import_priv_n(size_t inlen, const uint8_t *der) {
  @result     Key is initialized using the data in the PKCS#1 message.
  */
 
-CC_CONST CC_INLINE CC_NONNULL_TU((1)) CC_NONNULL((3))
+CC_INLINE CC_NONNULL((1, 3))
 int ccrsa_import_priv(ccrsa_full_ctx_t key, size_t inlen, const uint8_t *der) {
     return (ccder_decode_rsa_priv(key, der, der+inlen) == NULL);
 }
 
-
-CC_NONNULL_TU((1)) CC_NONNULL2
+/*!
+@function   ccrsa_get_pubkey_components
+@abstract   Copy each component of the public key to the given buffers
+
+@param      pubkey                       Public key
+@param      modulus                     Buffer to the output buffer for the modulus
+@param      modulusLength        Pointer to the byte size allocated for the modulus, updated with actual output size
+@param      exponent                  Buffer to the output buffer for the exponent
+@param      exponentLength     Pointer to the byte size allocated for the exponent, updated with actual output size
+@return     0 is success, not 0 in case of error
+@discussion if either allocated buffer length is insufficient, the function returns an error
+*/
+CC_NONNULL((1, 2))
 int ccrsa_get_pubkey_components(const ccrsa_pub_ctx_t pubkey, uint8_t *modulus, size_t *modulusLength, uint8_t *exponent, size_t *exponentLength);
 
-CC_NONNULL_TU((1)) CC_NONNULL2
+/*!
+@function   ccrsa_get_fullkey_components
+@abstract   Copy each component of the public key to the given buffers
+
+@param      key                              Full key
+@param      modulus                     Buffer to the output buffer for the modulus
+@param      modulusLength        Pointer to the byte size allocated for the modulus, updated with actual output size
+@param      exponent                  Buffer to the output buffer for the exponent
+@param      exponentLength     Pointer to the byte size allocated for the exponent, updated with actual output size
+@param      p                                  Buffer to the output buffer for the first prime factor of the modulus
+@param      pLength                     Pointer to the byte size allocated for the prime factor, updated with actual output size
+@param      q                                  Buffer to the output buffer for the second prime factor of the modulus
+@param      qLength                     Pointer to the byte size allocated for the prime factor, updated with actual output size
+
+@return     0 is success, not 0 in case of error
+@discussion if either allocated buffer length is insufficient, the function returns an error
+*/
+CC_NONNULL((1, 2))
 int ccrsa_get_fullkey_components(const ccrsa_full_ctx_t key, uint8_t *modulus, size_t *modulusLength, uint8_t *exponent, size_t *exponentLength,
                                  uint8_t *p, size_t *pLength, uint8_t *q, size_t *qLength);