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 ¶msl, &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, ¶ms, ¶msl) 183 && !parse_aid(¶ms, ¶msl, &ha, &hal, &hap, &hapl)) 184 return 0; 185 if (derr_header(DERC_CONTEXT, true, 1, NULL, ¶ms, ¶msl) 186 && !parse_aid(¶ms, ¶msl, &mga, &mgal, &mgap, &mgapl)) 187 return 0; 188 if (derr_header(DERC_CONTEXT, true, 2, NULL, ¶ms, ¶msl) 189 && !derr_integer(&sl, -1, ¶ms, ¶msl)) 190 return 0; 191 if (derr_header(DERC_CONTEXT, true, 3, NULL, ¶ms, ¶msl) 192 && !derr_integer(&tb, -1, ¶ms, ¶msl)) 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(¶ms, ¶msl, &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 }