/ libder / test_read_rsapss.c
test_read_rsapss.c
  1  #include <stdio.h>
  2  #include <stdlib.h>
  3  #include <unistd.h>
  4  #include "derr.h"
  5  
  6  /*
  7   * This tries to read an RSA key with PSS parameters in a PKCS#8 form,
  8   * received on stdin
  9   */
 10  
 11  const char prog[] = "test_read_rsapss";
 12  
 13  /*
 14   * From https://www.rfc-editor.org/rfc/rfc5280#section-4.1.1.2
 15   *
 16   * AlgorithmIdentifier  ::=  SEQUENCE  {
 17   *      algorithm               OBJECT IDENTIFIER,
 18   *      parameters              ANY DEFINED BY algorithm OPTIONAL
 19   * }
 20   */
 21  int parse_aid(derr_byte **der, size_t *derl,
 22                derr_byte **aid_oid, size_t *aid_oidl,
 23                derr_byte **aid_params, size_t *aid_paramsl)
 24  {
 25    derr_byte *aid = NULL;
 26    size_t aid_len = 0;
 27    derr_byte *oid = NULL;
 28    size_t oidl = 0;
 29    derr_byte *params = NULL;
 30    size_t paramsl = 0;
 31    derr_byte *d = *der;
 32    size_t dl = *derl;
 33  
 34    if (!derr_header(DERC_UNIVERSAL, true, DERP_SEQUENCE,
 35                     &aid_len, &d, &dl))
 36      return 0;
 37    aid = d;
 38  
 39    /* Advance the main DER pointer past the OID */
 40    d += aid_len;
 41    dl -= aid_len;
 42  
 43    if (!derr_header(DERC_UNIVERSAL, false, DERP_OBJECT,
 44                     &oidl, &aid, &aid_len))
 45      return 0;
 46    oid = aid;
 47    if (aid_len > 0) {
 48      params = aid + oidl;
 49      paramsl = aid_len - oidl;
 50    }
 51  
 52    *aid_oid = oid;
 53    *aid_oidl = oidl;
 54    *aid_params = params;
 55    *aid_paramsl = paramsl;
 56  
 57    /* Finish up */
 58    *der = d;
 59    *derl = dl;
 60  
 61    return 1;
 62  }
 63  
 64  /*
 65   * From https://www.rfc-editor.org/rfc/rfc5208#section-5
 66   *
 67   * PrivateKeyInfo ::= SEQUENCE {
 68   *   version                   Version,
 69   *   privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
 70   *   privateKey                PrivateKey,
 71   *   attributes           [0]  IMPLICIT Attributes OPTIONAL }
 72   *
 73   * Version ::= INTEGER
 74   *
 75   * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
 76   *
 77   * PrivateKey ::= OCTET STRING
 78   *
 79   * Attributes ::= SET OF Attribute
 80   */
 81  int parse_pkcs8(derr_byte **der, size_t *derl,
 82                  derr_byte **aid_oid, size_t *aid_oidl,
 83                  derr_byte **aid_params, size_t *aid_paramsl,
 84                  derr_byte **privatekey, size_t *privatekeyl)
 85  {
 86    derr_byte *pkcs8 = NULL;
 87    size_t pkcs8l = 0;
 88    uintmax_t v = 0;
 89    derr_byte *d = *der;
 90    size_t dl = *derl;
 91  
 92    if (!derr_header(DERC_UNIVERSAL, true, DERP_SEQUENCE,
 93                     &pkcs8l, &d, &dl))
 94      return 0;
 95    /* The contents should occupy the whole DER blob */
 96    if (pkcs8l != dl)
 97      return 0;
 98  
 99    pkcs8 = d;
100  
101    /* Advance the main DER pointer past the OID */
102    d += pkcs8l;
103    dl -= pkcs8l;
104  
105    if (!derr_integer(&v, -1, &pkcs8, &pkcs8l)
106        || v != 0
107        || !parse_aid(&pkcs8, &pkcs8l, aid_oid, aid_oidl, aid_params, aid_paramsl)
108        || !derr_header(DERC_UNIVERSAL, false, DERP_OCTET_STRING,
109                        privatekeyl, &pkcs8, &pkcs8l))
110      return 0;
111    *privatekey = pkcs8;
112  
113    if (pkcs8l != *privatekeyl)
114      return 0;
115  
116    /* Finish up */
117    *der = d;
118    *derl = dl;
119  
120    return 1;
121  }
122  
123  /*
124   * From https://www.rfc-editor.org/rfc/rfc8017#appendix-A.2.3
125   *
126   * RSASSA-PSS-params ::= SEQUENCE {
127   *     hashAlgorithm      [0] HashAlgorithm      DEFAULT sha1,
128   *     maskGenAlgorithm   [1] MaskGenAlgorithm   DEFAULT mgf1SHA1,
129   *     saltLength         [2] INTEGER            DEFAULT 20,
130   *     trailerField       [3] TrailerField       DEFAULT trailerFieldBC
131   * }
132   *
133   * HashAlgorithm ::= AlgorithmIdentifier { {OAEP-PSSDigestAlgorithms} }
134   *
135   * MaskGenAlgorithm ::= AlgorithmIdentifier { {PKCS1MGFAlgorithms} }
136   *
137   * PKCS1MGFAlgorithms    ALGORITHM-IDENTIFIER ::= {
138   *     { OID id-mgf1 PARAMETERS HashAlgorithm },
139   *     ...  -- Allows for future expansion --
140   * }
141   *
142   * TrailerField ::= INTEGER { trailerFieldBC(1) }
143   */
144  int parse_rsapss_params(derr_byte **der, size_t *derl,
145                          derr_byte **pss_hashalg, size_t *pss_hashalgl,
146                          derr_byte **pss_maskalg, size_t *pss_maskalgl,
147                          derr_byte **pss_maskalg_params, size_t *pss_maskalg_paramsl,
148                          intmax_t *pss_saltl, intmax_t *pss_trailerbyte)
149  {
150    derr_byte *params = NULL;
151    size_t paramsl = 0;
152    derr_byte *ha = NULL;
153    size_t hal = 0;
154    derr_byte *hap = NULL;
155    size_t hapl = 0;
156    derr_byte *mga = NULL;
157    size_t mgal = 0;
158    derr_byte *mgap = NULL;
159    size_t mgapl = 0;
160    derr_byte *mgha = NULL;
161    size_t mghal = 0;
162    derr_byte *mghap = NULL;
163    size_t mghapl = 0;
164    intmax_t sl, tb;
165    derr_byte *d = *der;
166    size_t dl = *derl;
167  
168    if (!derr_header(DERC_UNIVERSAL, true, DERP_SEQUENCE,
169                     &paramsl, &d, &dl))
170      return 0;
171    /* The parameters should occupy the whole DER blob */
172    if (paramsl != dl)
173      return 0;
174  
175    params = d;
176  
177    /* Advance the main DER pointer past the OID */
178    d += paramsl;
179    dl -= paramsl;
180  
181    /* Parse RSASSA-PSS-params */
182    if (derr_header(DERC_CONTEXT, true, 0, NULL, &params, &paramsl)
183        && !parse_aid(&params, &paramsl, &ha, &hal, &hap, &hapl))
184      return 0;
185    if (derr_header(DERC_CONTEXT, true, 1, NULL, &params, &paramsl)
186        && !parse_aid(&params, &paramsl, &mga, &mgal, &mgap, &mgapl))
187      return 0;
188    if (derr_header(DERC_CONTEXT, true, 2, NULL, &params, &paramsl)
189        && !derr_integer(&sl, -1, &params, &paramsl))
190      return 0;
191    if (derr_header(DERC_CONTEXT, true, 3, NULL, &params, &paramsl)
192        && !derr_integer(&tb, -1, &params, &paramsl))
193      return 0;
194  
195    /* Did we reach the end? */
196    if (paramsl != 0)
197      return 0;
198  
199    /* Parse MaskGenAlgorithm parameters */
200    params = mgap;
201    paramsl = mgapl;
202    if (!parse_aid(&params, &paramsl, &mgha, &mghal, &mghap, &mghapl))
203      return 0;
204  
205    *pss_hashalg = ha;
206    *pss_hashalgl = hal;
207    *pss_maskalg = mgha;
208    *pss_maskalgl = mghal;
209    *pss_maskalg_params = mghap;
210    *pss_maskalg_paramsl = mghapl;
211    *pss_saltl = sl;
212    *pss_trailerbyte = tb;
213    
214    /* Finish up */
215    *der = d;
216    *derl = dl;
217  
218    return 1;
219  }
220  
221  /*
222   * From https://www.rfc-editor.org/rfc/rfc8017#appendix-A.1.2
223   *
224   * RSAPrivateKey ::= SEQUENCE {
225   *     version           Version,
226   *     modulus           INTEGER,  -- n
227   *     publicExponent    INTEGER,  -- e
228   *     privateExponent   INTEGER,  -- d
229   *     prime1            INTEGER,  -- p
230   *     prime2            INTEGER,  -- q
231   *     exponent1         INTEGER,  -- d mod (p-1)
232   *     exponent2         INTEGER,  -- d mod (q-1)
233   *     coefficient       INTEGER,  -- (inverse of q) mod p
234   *     otherPrimeInfos   OtherPrimeInfos OPTIONAL
235   * }
236   */
237  
238  int parse_rsa_privatekey(derr_byte **der, size_t *derl,
239                           derr_byte **rsa_n, size_t *rsa_nl,
240                           derr_byte **rsa_e, size_t *rsa_el,
241                           derr_byte **rsa_d, size_t *rsa_dl,
242                           derr_byte **rsa_p, size_t *rsa_pl,
243                           derr_byte **rsa_q, size_t *rsa_ql,
244                           derr_byte **rsa_dmp, size_t *rsa_dmpl,
245                           derr_byte **rsa_dmq, size_t *rsa_dmql,
246                           derr_byte **rsa_iqmp, size_t *rsa_iqmpl)
247  {
248    intmax_t v = 0;
249    derr_byte *d = *der;
250    size_t dl = *derl;
251  
252    if (!derr_header(DERC_UNIVERSAL, true, DERP_SEQUENCE, NULL, &d, &dl))
253      return 0;
254    if (!derr_integer(&v, -1, &d, &dl) || v != 0)
255      return 0;
256    if (!derr_header(DERC_UNIVERSAL, false, DERP_INTEGER, rsa_nl, &d, &dl))
257      return 0;
258    *rsa_n = d;
259    d += *rsa_nl;
260    dl -= *rsa_nl;
261    if (!derr_header(DERC_UNIVERSAL, false, DERP_INTEGER, rsa_el, &d, &dl))
262      return 0;
263    *rsa_e = d;
264    d += *rsa_el;
265    dl -= *rsa_el;
266    if (!derr_header(DERC_UNIVERSAL, false, DERP_INTEGER, rsa_dl, &d, &dl))
267      return 0;
268    *rsa_d = d;
269    d += *rsa_dl;
270    dl -= *rsa_dl;
271    if (!derr_header(DERC_UNIVERSAL, false, DERP_INTEGER, rsa_pl, &d, &dl))
272      return 0;
273    *rsa_p = d;
274    d += *rsa_pl;
275    dl -= *rsa_pl;
276    if (!derr_header(DERC_UNIVERSAL, false, DERP_INTEGER, rsa_ql, &d, &dl))
277      return 0;
278    *rsa_q = d;
279    d += *rsa_ql;
280    dl -= *rsa_ql;
281    if (!derr_header(DERC_UNIVERSAL, false, DERP_INTEGER, rsa_dmpl, &d, &dl))
282      return 0;
283    *rsa_dmp = d;
284    d += *rsa_dmpl;
285    dl -= *rsa_dmpl;
286    if (!derr_header(DERC_UNIVERSAL, false, DERP_INTEGER, rsa_dmql, &d, &dl))
287      return 0;
288    *rsa_dmq = d;
289    d += *rsa_dmql;
290    dl -= *rsa_dmql;
291    if (!derr_header(DERC_UNIVERSAL, false, DERP_INTEGER, rsa_iqmpl, &d, &dl))
292      return 0;
293    *rsa_iqmp = d;
294    d += *rsa_iqmpl;
295    dl -= *rsa_iqmpl;
296    
297    /* Finish up */
298    *der = d;
299    *derl = dl;
300  
301    return 1;
302  }
303  
304  int main()
305  {
306    derr_byte *der = NULL;
307    size_t derl = 0, dersz = 0;
308    ssize_t readl = 0;
309  
310    /* Slurp stdin, 16KiB at a time */
311    do {
312      derl += readl;
313      if (derl == dersz) {
314        dersz += 1 << 14;         /* 16Ki == 2^14 */
315        if ((der = realloc(der, dersz)) == NULL) {
316          /* Oops, we lost it */
317          perror(prog);
318          exit(1);
319        }
320      }
321    } while ((readl = read(0, der + derl, dersz - derl)) > 0);
322    if (readl < 0) {
323      /* Oops, something's wrong with stdin */
324      perror(prog);
325      exit(1);
326    }
327    fprintf(stderr, "LOG: Read %zu bytes\n", derl);
328  
329    derr_byte *pkalg = NULL;
330    size_t pkalgl = 0;
331    derr_byte *pkparams = NULL;
332    size_t pkparamsl = 0;
333    derr_byte *pk = NULL;
334    size_t pkl = 0;
335    derr_byte *psshashalg = NULL;
336    size_t psshashalgl = 0;
337    derr_byte *pssmaskalg = NULL;
338    size_t pssmaskalgl = 0;
339    derr_byte *pssmaskalgp = NULL;
340    size_t pssmaskalgpl = 0;
341    intmax_t psssaltlen = 0;
342    intmax_t psstrailerbyte = 0;
343    derr_byte *rsa_n = NULL;
344    size_t rsa_nl = 0;
345    derr_byte *rsa_e = NULL;
346    size_t rsa_el = 0;
347    derr_byte *rsa_d = NULL;
348    size_t rsa_dl = 0;
349    derr_byte *rsa_p = NULL;
350    size_t rsa_pl = 0;
351    derr_byte *rsa_q = NULL;
352    size_t rsa_ql = 0;
353    derr_byte *rsa_dmp = NULL;
354    size_t rsa_dmpl = 0;
355    derr_byte *rsa_dmq = NULL;
356    size_t rsa_dmql = 0;
357    derr_byte *rsa_iqmp = NULL;
358    size_t rsa_iqmpl = 0;
359  
360    if (!parse_pkcs8(&der, &derl,
361                     &pkalg, &pkalgl, &pkparams, &pkparamsl, &pk, &pkl)
362        || !(pkparamsl == 0
363             || parse_rsapss_params(&pkparams, &pkparamsl,
364                                    &psshashalg, &psshashalgl,
365                                    &pssmaskalg, &pssmaskalgl,
366                                    &pssmaskalgp, &pssmaskalgpl,
367                                    &psssaltlen, &psstrailerbyte))
368        || !parse_rsa_privatekey(&pk, &pkl,
369                                 &rsa_n, &rsa_nl,
370                                 &rsa_e, &rsa_el,
371                                 &rsa_d, &rsa_dl,
372                                 &rsa_p, &rsa_pl,
373                                 &rsa_q, &rsa_ql,
374                                 &rsa_dmp, &rsa_dmpl,
375                                 &rsa_dmq, &rsa_dmql,
376                                 &rsa_iqmp, &rsa_iqmpl)) {
377      fprintf(stderr, "Failed to parse an RSA-PSS key\n");
378      exit(1);
379    }
380    
381      fprintf(stderr, "yay!\n");
382    exit(0);
383  }