/* Get the BIT STRING key and plug into RSA structure. */ int32 getAsnRsaPubKey(psPool_t *pool, unsigned char **pp, uint32 len, psRsaKey_t *pubKey) { unsigned char *p = *pp; uint32 pubKeyLen, seqLen; int32 ignore_bits; memset(pubKey, 0x0, sizeof(psRsaKey_t)); if (len < 1 || (*(p++) != ASN_BIT_STRING) || getAsnLength(&p, len - 1, &pubKeyLen) < 0 || (len - 1) < pubKeyLen) { psTraceCrypto("Initial parse error in getAsnRsaPubKey\n"); return PS_PARSE_FAIL; } ignore_bits = *p++; /* We assume this is always zero */ psAssert(ignore_bits == 0); if (getAsnSequence(&p, pubKeyLen, &seqLen) < 0 || getAsnBig(pool, &p, seqLen, &pubKey->N) < 0 || getAsnBig(pool, &p, seqLen, &pubKey->e) < 0) { psTraceCrypto("Secondary parse error in getAsnRsaPubKey\n"); return PS_PARSE_FAIL; } pubKey->size = pstm_unsigned_bin_size(&pubKey->N); *pp = p; return PS_SUCCESS; }
/* Implementation specific OID parser for suppported RSA algorithms */ int32 getAsnAlgorithmIdentifier(unsigned char **pp, uint32 len, int32 *oi, int32 isPubKey, int32 *paramLen) { unsigned char *p = *pp, *end; int32 plen; uint32 llen, arcLen; end = p + len; if (len < 1 || getAsnSequence(&p, len, &llen) < 0) { psTraceCrypto("getAsnAlgorithmIdentifier failed on inital parse\n"); return PS_PARSE_FAIL; } if (end - p < 1) { psTraceCrypto("Malformed algorithmId\n"); return PS_LIMIT_FAIL; } plen = end - p; if (*(p++) != ASN_OID || getAsnLength(&p, (uint32)(end - p), &arcLen) < 0 || llen < arcLen) { psTraceCrypto("Malformed algorithmId 2\n"); return PS_PARSE_FAIL; } if (end - p < 2) { psTraceCrypto("Malformed algorithmId 3\n"); return PS_LIMIT_FAIL; } if (isPubKey && (*p != 0x2a) && (*(p + 1) != 0x86)) { /* Expecting DSA here if not RSA, but OID doesn't always match */ psTraceCrypto("Unsupported algorithm identifier\n"); return PS_UNSUPPORTED_FAIL; } *oi = 0; while (arcLen-- > 0) { *oi += (int32)*p; p++; } /* Each of these cases might have a trailing NULL parameter. Skip it */ plen -= (end - p); *paramLen = llen - plen; if (*p != ASN_NULL) { *pp = p; return PS_SUCCESS; } if (end - p < 2) { psTraceCrypto("Malformed algorithmId 4\n"); return PS_LIMIT_FAIL; } *paramLen -= 2; *pp = p + 2; return PS_SUCCESS; }
/** Parse an RSA private key from a PKCS#1 byte stream. @see ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf */ int32_t psRsaParsePkcs1PrivKey(psPool_t *pool, const unsigned char *p, psSize_t size, psRsaKey_t *key) { RSA *rsa; # ifndef USE_D2I const unsigned char *end, *seq; int32_t version; psSize_t seqlen; # endif # ifdef USE_D2I if ((rsa = d2i_RSAPrivateKey(NULL, &p, size)) == NULL) { return PS_PARSE_FAIL; } # else if ((rsa = RSA_new()) == NULL) { return PS_MEM_FAIL; } end = p + size; if (getAsnSequence(&p, size, &seqlen) < 0) { RSA_free(rsa); goto L_FAIL; } seq = p; if (getAsnInteger(&p, (uint16_t) (end - p), &version) < 0 || version != 0 || getBig(&p, (uint16_t) (end - p), &rsa->n) < 0 || getBig(&p, (uint16_t) (end - p), &rsa->e) < 0 || getBig(&p, (uint16_t) (end - p), &rsa->d) < 0 || getBig(&p, (uint16_t) (end - p), &rsa->p) < 0 || getBig(&p, (uint16_t) (end - p), &rsa->q) < 0 || getBig(&p, (uint16_t) (end - p), &rsa->dmp1) < 0 || getBig(&p, (uint16_t) (end - p), &rsa->dmq1) < 0 || getBig(&p, (uint16_t) (end - p), &rsa->iqmp) < 0 || (uint16_t) (p - seq) != seqlen) { RSA_free(rsa); goto L_FAIL; } rsa->version = version; # endif /* RSA_print_fp(stdout, rsa, 0); */ *key = rsa; return PS_SUCCESS; L_FAIL: psTraceIntCrypto("psRsaParsePkcs1PrivKey error on byte %d\n", p - (end - size)); return PS_PARSE_FAIL; }
/* Parse DER encoded asn.1 RSA public key out of a certificate stream. We reach here with 'pp' pointing to the byte after the algorithm identifier. */ int32_t psRsaParseAsnPubKey(psPool_t *pool, const unsigned char **pp, psSize_t len, psRsaKey_t *key, unsigned char sha1KeyHash[SHA1_HASH_SIZE]) { # ifdef USE_SHA1 psDigestContext_t dc; # endif const unsigned char *p = *pp; RSA *rsa; psSize_t keylen; # ifndef USE_D2I psSize_t seqlen; # endif if (len < 1 || (*(p++) != ASN_BIT_STRING) || getAsnLength(&p, len - 1, &keylen)) { goto L_FAIL; } /* ignored bits field should be zero */ if (*p++ != 0) { goto L_FAIL; } keylen--; # ifdef USE_SHA1 /* A public key hash is used in PKI tools (OCSP, Trusted CA indication). Standard RSA form - SHA-1 hash of the value of the BIT STRING subjectPublicKey [excluding the tag, length, and number of unused bits] */ psSha1Init(&dc.sha1); psSha1Update(&dc.sha1, p, keylen); psSha1Final(&dc.sha1, sha1KeyHash); # endif # ifdef USE_D2I /* OpenSSL expects to parse after the ignored bits field */ if ((rsa = d2i_RSAPublicKey(NULL, &p, keylen)) == NULL) { goto L_FAIL; } # else /* We can manually create the structures as OpenSSL would */ rsa = RSA_new(); if (getAsnSequence(&p, keylen, &seqlen) < 0 || getBig(&p, seqlen, &rsa->n) < 0 || getBig(&p, seqlen, &rsa->e) < 0) { RSA_free(rsa); goto L_FAIL; } # endif /* RSA_print_fp(stdout, rsa, 0); */ *pp = p; *key = rsa; return PS_SUCCESS; L_FAIL: psTraceIntCrypto("psRsaParseAsnPubKey error on byte %d\n", p - *pp); return PS_PARSE_FAIL; }