.. _mozilla_projects_nss_nss_sample_code_nss_sample_code_sample4:

NSS Sample Code sample4
=======================

.. _nss_sample_code_4_pki_encryption:

`NSS Sample Code 4: PKI Encryption <#nss_sample_code_4_pki_encryption>`__
-------------------------------------------------------------------------

.. container::

   .. code::

      /* Example code to illustrate PKI crypto ops (encrypt with public key,
       * decrypt with private key)
       *
       * Code assumes that you have set up a NSS database with a certificate
       * and a private key. The db password should be "test" and the cert
       * nickname should be "TestCA"
       * Here is one way of doing it:
       *   # create CA cert db, if -f not provided, prompts for passwd
       *   $ certutil -N -d .
       *   # create CA cert, self-signed, generates key-pair, prompts for key
       *   # type, cert type etc
       *   # answers for prompts: 5,9,n,y,-1,n,5,6,7,9,n
       *   $ certutil -S -s "CN=Test CA, O=BOGUS Inc, L=Mtn View, ST=CA, C=US"  \
       *     -n TestCA -t CTu,CTu,CTu -v 60 -x -d . -1 -2 -5
       *
       * There are many ways to setup a public/private key to use - this
       * example shows one of them.
       *
       * This example does not do any padding. It simply encrypts/decrypts a block
       * of length equal to modulus length of the public/private key.
       */


      #include "nss.h"
      #include "pk11pub.h"


      /* this callback is responsible for returning the password to the NSS
       * key database. for example purposes, this function hardcodes the password.
       * In a real app, this function should obtain the password using secure means
       * such as prompting an operator, or retrieving it over a secure communication
       * channel
       */
      char *passwdcb(PK11SlotInfo *info, PRBool retry, void *arg);


      int main(int argc, char **argv)
      {
        SECStatus          rv;
        CERTCertificate   *cert = NULL;
        SECKEYPublicKey   *pubkey = NULL;
        SECKEYPrivateKey  *pvtkey = NULL;
        int                modulus_len, i, outlen;
        char              *buf1 = NULL;
        char              *buf2 = NULL;

        /* Initialize NSS */
        PK11_SetPasswordFunc(passwdcb);
        rv = NSS_Init(".");
        if (rv != SECSuccess)
        {
          fprintf(stderr, "NSS initialization failed (err %d)\n",
                  PR_GetError());
          goto cleanup;
        }

        cert = PK11_FindCertFromNickname("TestCA", NULL);
        if (cert == NULL)
        {
          fprintf(stderr, "Couldn't find cert TestCA in NSS db (err %d)\n",
                  PR_GetError());
          goto cleanup;
        }

        pubkey = CERT_ExtractPublicKey(cert);
        if (pubkey == NULL)
        {
          fprintf(stderr, "Couldn't extract public key from cert TestCA (err %d)\n",
                  PR_GetError());
          goto cleanup;
        }

        modulus_len = SECKEY_PublicKeyStrength(pubkey);
        fprintf(stderr, "Public Key Modulus %d bytes\n", modulus_len);
        buf1 = (char *)malloc(modulus_len);
        buf2 = (char *)malloc(modulus_len);

        /* initialize buf1 */
        for (i=0;i<modulus_len;i++)
        {
          buf1[i]= (i %26) + 'A';
        }
        buf1[modulus_len-1] = '\0';
        fprintf(stderr, "Buffer being encrypted = \n%s\n", buf1);

        /* encrypt buf1, result will be in buf2 */
        rv = PK11_PubEncryptRaw(pubkey, buf2, buf1, modulus_len, NULL);
        if (rv != SECSuccess)
        {
          fprintf(stderr, "Encrypt with Public Key failed (err %d)\n",
                  PR_GetError());
          goto cleanup;
        }

        pvtkey = PK11_FindKeyByAnyCert(cert, NULL);
        if (pvtkey == NULL)
        {
          fprintf(stderr, "Couldn't find private key for cert TestCA (err %d)\n",
                  PR_GetError());
          goto cleanup;
        }

        /* clear buf1 */
        for (i=0;i<modulus_len;i++)
        {
          buf1[i]= '\0';
        }

        /* decrypt buf2, result will be in buf1 */
        rv = PK11_PubDecryptRaw(pvtkey, buf1, &outlen, modulus_len, buf2,
                                modulus_len);
        if (rv != SECSuccess)
        {
          fprintf(stderr, "Decrypt with Private Key failed (err %d)\n",
                  PR_GetError());
          goto cleanup;
        }

        fprintf(stderr, "Result of decryption, outlen = %d\n", outlen);
        fprintf(stderr, "Result of decryption, buf = \n%s\n", buf1);

        exit(0);

      cleanup:
        if (cert)
          CERT_DestroyCertificate(cert);
        if (pubkey)
          SECKEY_DestroyPublicKey(pubkey);
        if (pvtkey)
          SECKEY_DestroyPrivateKey(pvtkey);
        if (buf1)
          free(buf1);
        if (buf2)
          free(buf2);
        exit(1);
      }

      char *passwdcb(PK11SlotInfo *info, PRBool retry, void *arg)
      {
        if (!retry)
          return PL_strdup("test");
        else
          return NULL;
      }