summaryrefslogtreecommitdiff
path: root/doc/rst/legacy/nss_sample_code/nss_sample_code_sample4/index.rst
blob: cfe86d4d6984c235aa578644105fc041c6e63a48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
.. _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:: notranslate

      /* 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;
      }