/** * \file rsa.h */ #ifndef _RSA_H #define _RSA_H #ifdef __cplusplus extern "C" { #endif #include "bignum.h" #define ERR_RSA_BAD_INPUT_DATA 0x0300 #define ERR_RSA_INVALID_PADDING 0x0310 #define ERR_RSA_KEY_GEN_FAILED 0x0320 #define ERR_RSA_KEY_CHK_FAILED 0x0330 #define ERR_RSA_PUBLIC_FAILED 0x0340 #define ERR_RSA_PRIVATE_FAILED 0x0350 #define ERR_RSA_VERIFY_FAILED 0x0360 /* * PKCS#1 stuff */ #define RSA_RAW 0 #define RSA_MD2 2 #define RSA_MD4 3 #define RSA_MD5 4 #define RSA_SHA1 5 #define RSA_SIGN 0x01 #define RSA_CRYPT 0x02 /* * DigestInfo ::= SEQUENCE { * digestAlgorithm DigestAlgorithmIdentifier, * digest Digest } * * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * * Digest ::= OCTET STRING */ #define ASN1_HASH_MDX \ "\x30\x20\x30\x0C\x06\x08\x2A\x86\x48" \ "\x86\xF7\x0D\x02\x00\x05\x00\x04\x10" #define ASN1_HASH_SHA1 \ "\x30\x21\x30\x09\x06\x05\x2B\x0E\x03" \ "\x02\x1A\x05\x00\x04\x14" typedef struct { int ver; /*!< should be 0 */ int len; /*!< size(N) in chars */ mpi N; /*!< public modulus */ mpi E; /*!< public exponent */ mpi D; /*!< private exponent */ mpi P; /*!< 1st prime factor */ mpi Q; /*!< 2nd prime factor */ mpi DP; /*!< D mod (P - 1) */ mpi DQ; /*!< D mod (Q - 1) */ mpi QP; /*!< inverse of Q % P */ mpi RN; /*!< cached R^2 mod N */ mpi RP; /*!< cached R^2 mod P */ mpi RQ; /*!< cached R^2 mod Q */ } rsa_context; /** * \brief Generate an RSA keypair * * \param ctx RSA context to be initialized * \param nbits size of the public key in bits * \param exponent public exponent (e.g., 65537) * \param rng_f points to the RNG function * \param rng_d points to the RNG data * * \return 0 if successful, or an ERR_RSA_XXX error code */ int rsa_gen_key( rsa_context *ctx, int nbits, int exponent, int (*rng_f)(void *), void *rng_d ); /** * \brief Perform an RSA public key operation * * \return 0 if successful, or an ERR_RSA_XXX error code * * \note This function does not take care of message * padding: both ilen and olen must be equal to * the modulus size (ctx->len). Also, be sure * to set input[0] = 0. */ int rsa_public( rsa_context *ctx, unsigned char *input, int ilen, unsigned char *output, int *olen ); /** * \brief Perform an RSA private key operation * * \return 0 if successful, or an ERR_RSA_XXX error code * * \note This function does not take care of message * padding: both ilen and olen must be equal to * the modulus size (ctx->len). Also, be sure * to set input[0] = 0. */ int rsa_private( rsa_context *ctx, unsigned char *input, int ilen, unsigned char *output, int *olen ); /** * \brief Return 0 if the public key is valid, * or ERR_RSA_KEY_CHECK_FAILED */ int rsa_check_pubkey( rsa_context *ctx ); /** * \brief Return 0 if the private key is valid, * or ERR_RSA_KEY_CHECK_FAILED */ int rsa_check_privkey( rsa_context *ctx ); /** * \brief Add the PKCS#1 v1.5 padding and do a public RSA * * \param ctx RSA context * \param input buffer holding the data to be encrypted * \param ilen length of the plaintext; cannot be longer * than the modulus, minus 3+8 for padding * \param output buffer that will hold the ciphertext * \param olen must be the same as the modulus size * (for example, 128 if RSA-1024 is used) * * \return 0 if successful, or an ERR_RSA_XXX error code */ int rsa_pkcs1_encrypt( rsa_context *ctx, unsigned char *input, int ilen, unsigned char *output, int *olen ); /** * \brief Do a private RSA, removes the PKCS#1 v1.5 padding * * \param ctx RSA context * \param input buffer holding the encrypted data * \param ilen must be the same as the modulus size * \param output buffer that will hold the plaintext * \param olen size of output buffer, will be updated * to contain the length of the plaintext * * \return 0 if successful, or an ERR_RSA_XXX error code */ int rsa_pkcs1_decrypt( rsa_context *ctx, unsigned char *input, int ilen, unsigned char *output, int *olen ); /** * \brief Perform a private RSA to sign a message digest * * \param ctx RSA context * \param alg_id RSA_RAW, RSA_MD2/4/5 or RSA_SHA1 * \param hash buffer holding the message digest * \param hashlen message digest length * \param sig buffer that will hold the ciphertext * \param siglen must be the same as the modulus size * (for example, 128 if RSA-1024 is used) * * \return 0 if the signing operation was successful, * or an ERR_RSA_XXX error code */ int rsa_pkcs1_sign( rsa_context *ctx, int alg_id, unsigned char *hash, int hashlen, unsigned char *sig, int siglen ); /** * \brief Perform a public RSA and check the message digest * * \param ctx points to an RSA public key * \param alg_id RSA_RAW, RSA_MD2/4/5 or RSA_SHA1 * \param hash buffer holding the message digest * \param hashlen message digest length * \param sig buffer holding the ciphertext * \param siglen must be the same as the modulus size * * \return 0 if the verify operation was successful, * or an ERR_RSA_XXX error code */ int rsa_pkcs1_verify( rsa_context *ctx, int alg_id, unsigned char *hash, int hashlen, unsigned char *sig, int siglen ); /** * \brief Free the components of an RSA key */ void rsa_free( rsa_context *ctx ); /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int rsa_self_test( void ); #ifdef __cplusplus } #endif #endif