Exemplo n.º 1
0
Arquivo: asn1.c Projeto: B-Rich/NUL
/*
	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;
}
Exemplo n.º 2
0
Arquivo: asn1.c Projeto: B-Rich/NUL
/*
	Callback to extract a big int (stream of bytes) from the DER stream
*/
int32 getAsnBig(psPool_t *pool, unsigned char **pp, uint32 len, pstm_int *big)
{
	unsigned char	*p = *pp;
	uint32			vlen;	

	if (len < 1 || *(p++) != ASN_INTEGER ||
			getAsnLength(&p, len - 1, &vlen) < 0 || (len - 1) < vlen)  {
		psTraceCrypto("ASN getBig failed\n");
		return PS_PARSE_FAIL;
	}
/*
	Make a smart size since we know the length
*/
	if (pstm_init_for_read_unsigned_bin(pool, big, vlen) != PSTM_OKAY) {
		return PS_MEM_FAIL;
	}
	if (pstm_read_unsigned_bin(big, p, vlen) != 0) {
		pstm_clear(big);
		psTraceCrypto("ASN getBig failed\n");
		return PS_PARSE_FAIL;
	}
	p += vlen;
	*pp = p;
	return PS_SUCCESS;
}
Exemplo n.º 3
0
Arquivo: asn1.c Projeto: B-Rich/NUL
/*
	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;
}
Exemplo n.º 4
0
Arquivo: asn1.c Projeto: B-Rich/NUL
/*
	Extract a set length from the DER stream
*/
int32 getAsnSet(unsigned char **pp, uint32 len, uint32 *setlen)
{
	unsigned char	*p = *pp;

	if (len < 1 || *(p++) != (ASN_SET | ASN_CONSTRUCTED) || 
			getAsnLength(&p, len - 1, setlen) < 0 || len < *setlen) {
		psTraceCrypto("ASN getSet failed\n");
		return PS_PARSE_FAIL;
	}
	*pp = p;
	return PS_SUCCESS;
}
Exemplo n.º 5
0
Arquivo: asn1.c Projeto: B-Rich/NUL
/*
	Get an integer
*/
int32 getAsnInteger(unsigned char **pp, uint32 len, int32 *val)
{
	unsigned char	*p = *pp, *end;
	uint32			ui,	vlen;
	int32			slen;

	end = p + len;
	if (len < 1 || *(p++) != ASN_INTEGER ||
			getAsnLength(&p, len - 1, &vlen) < 0) {
		psTraceCrypto("ASN getInteger failed from the start\n");
		return PS_PARSE_FAIL;
	}
/*
	This check prevents us from having a big positive integer where the 
	high bit is set because it will be encoded as 5 bytes (with leading 
	blank byte).  If that is required, a getUnsigned routine should be used
*/
	if (vlen > sizeof(int32) || (uint32)(end - p) < vlen) {
		psTraceCrypto("ASN getInteger had limit failure\n");
		return PS_LIMIT_FAIL;
	}
	ui = 0;
/*
	If high bit is set, it's a negative integer, so perform the two's compliment
	Otherwise do a standard big endian read (most likely case for RSA)
*/
	if (*p & 0x80) {
		while (vlen-- > 0) {
			ui = (ui << 8) | (*p ^ 0xFF);
			p++;
		}
		slen = (int32)ui;
		slen++;
		slen = -slen;
		*val = slen;
	} else {
		while (vlen-- > 0) {
			ui = (ui << 8) | *p;
			p++;
		}
		*val = (int32)ui;
	}
	*pp = p;
	return PS_SUCCESS;
}
Exemplo n.º 6
0
/**
    Convert big endian binary data to a native big number type.
    BN_bin2bn() converts the positive integer in big-endian form of length len
    at s into a BIGNUM and places it in ret.
    If ret is NULL, a new BIGNUM is created.
    BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
 */
static int32_t getBig(const unsigned char **pp, psSize_t len, BIGNUM **big)
{
    const unsigned char *p = *pp;
    psSize_t vlen;
    BIGNUM *bn;

    if (len < 1 || *(p++) != ASN_INTEGER ||
        getAsnLength(&p, len - 1, &vlen) < 0 || (len - 1) < vlen)
    {
        return PS_PARSE_FAIL;
    }
    if ((bn = BN_bin2bn(p, vlen, NULL)) == NULL)
    {
        return PS_MEM_FAIL;
    }
    /* BN_print_fp(stdout, bn); */
    *big = bn;
    *pp = p + vlen;
    return PS_SUCCESS;
}
Exemplo n.º 7
0
Arquivo: asn1.c Projeto: B-Rich/NUL
/* #define DISABLE_STRICT_ASN_LENGTH_CHECK */
int32 getAsnSequence(unsigned char **pp, uint32 len, uint32 *seqlen)
{
	unsigned char	*p = *pp;

	if (len < 1 || *(p++) != (ASN_SEQUENCE | ASN_CONSTRUCTED) || 
			getAsnLength(&p, len - 1, seqlen) < 0) {
		psTraceCrypto("ASN getSequence failed\n");	
		return PS_PARSE_FAIL;
	}
#ifndef DISABLE_STRICT_ASN_LENGTH_CHECK
	if (len < *seqlen) {
		/* It isn't cool but some encodings have an outer length layer that
			is smaller than the inner.  Normally you'll want this check but if
			you're hitting this case, you could try skipping it to see if there
			is an error in the encoding */
		psTraceCrypto("ASN_SEQUENCE parse found length greater than total\n");
		psTraceCrypto("Could try enabling DISABLE_STRICT_ASN_LENGTH_CHECK\n");
		return PS_LIMIT_FAIL;
	}
#endif	
	*pp = p;
	return PS_SUCCESS;
}
Exemplo n.º 8
0
/*
    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;
}