Example #1
0
/*
    Binary to struct helper for RSA public keys.
*/
int32 matrixRsaParsePubKey(psPool_t *pool, unsigned char *keyBuf,
                              int32 keyBufLen, sslRsaKey_t **key)
{
    unsigned char   *p, *end;
    int32           len;

    p = keyBuf;
    end = p + keyBufLen;
/*
    Supporting both the PKCS#1 RSAPublicKey format and the
    X.509 SubjectPublicKeyInfo format.  If encoding doesn't start with
    the SEQUENCE identifier for the SubjectPublicKeyInfo format, jump down
    to the RSAPublicKey subset parser and try that
*/
    if (getSequence(&p, (int32)(end - p), &len) == 0) {
        if (getAlgorithmIdentifier(&p, (int32)(end - p), &len, 1) < 0) {
            return -1;
        }
    }
/*
    Now have the DER stream to extract from in asnp
 */
    *key = psMalloc(pool, sizeof(sslRsaKey_t));
    if (*key == NULL) {
        return -8; /* SSL_MEM_ERROR */
    }
    memset(*key, 0x0, sizeof(sslRsaKey_t));
    if (getPubKey(pool, &p, (int32)(end - p), *key) < 0) {
        matrixRsaFreeKey(*key);
        *key = NULL;
        matrixStrDebugMsg("Unable to ASN parse public key\n", NULL);
        return -1;
    }
    return 0;
}
Example #2
0
/*
	Do the signature validation for a subject certificate against a
	known CA certificate
*/
int32 psAsnConfirmSignature(unsigned char *sigHash, unsigned char *sigOut,
							int32 sigLen)
{
	unsigned char	*end, *p = sigOut;
	unsigned char	hash[SSL_SHA1_HASH_SIZE];
	int32			len, oi;

	end = p + sigLen;
/*
	DigestInfo ::= SEQUENCE {
		digestAlgorithm DigestAlgorithmIdentifier,
		digest Digest }

	DigestAlgorithmIdentifier ::= AlgorithmIdentifier

	Digest ::= OCTET STRING
*/
	if (getSequence(&p, (int32)(end - p), &len) < 0) {
		return -1;
	}

/*
	Could be MD5 or SHA1
 */
	if (getAlgorithmIdentifier(&p, (int32)(end - p), &oi, 0) < 0) {
		return -1;
	}
	if ((*p++ != ASN_OCTET_STRING) ||
			asnParseLength(&p, (int32)(end - p), &len) < 0 || (end - p) <  len) {
		return -1;
	}
	memcpy(hash, p, len);
	if (oi == OID_MD5 || oi == OID_MD2) {
		if (len != SSL_MD5_HASH_SIZE) {
			return -1;
		}
	} else if (oi == OID_SHA1) {
		if (len != SSL_SHA1_HASH_SIZE) {
			return -1;
		}
	} else {
		return -1;
	}
/*
	hash should match sigHash
*/
	if (memcmp(hash, sigHash, len) != 0) {
		return -1;
	}
	return 0;
}
Example #3
0
/*
	Parse an X509 ASN.1 certificate stream
	http://www.faqs.org/rfcs/rfc2459.html section 4.1
*/
int32 matrixX509ParseCert(psPool_t *pool, unsigned char *pp, int32 size, 
						sslRsaCert_t **outcert)
{
	sslRsaCert_t		*cert;
	sslMd5Context_t		md5Ctx;
	sslSha1Context_t	sha1Ctx;
	unsigned char		*p, *end, *certStart, *certEnd;
	int32				certLen, len, parsing;
#ifdef USE_MD2
	sslMd2Context_t		md2Ctx;
#endif /* USE_MD2 */

/*
	Allocate the cert structure right away.  User MUST always call
	matrixX509FreeCert regardless of whether this function succeeds.
	memset is important because the test for NULL is what is used
	to determine what to free
*/
	*outcert = cert = psMalloc(pool, sizeof(sslRsaCert_t));
	if (cert == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memset(cert, '\0', sizeof(sslRsaCert_t));

	p = pp;
	end = p + size;
/*
		Certificate  ::=  SEQUENCE  {
		tbsCertificate		TBSCertificate,
		signatureAlgorithm	AlgorithmIdentifier,
		signatureValue		BIT STRING	}
*/
	parsing = 1;
	while (parsing) {
		if (getSequence(&p, (int32)(end - p), &len) < 0) {
			matrixStrDebugMsg("Initial cert parse error\n", NULL);
			return -1;
		}
		certStart = p;
/*	
		TBSCertificate  ::=  SEQUENCE  {
		version			[0]		EXPLICIT Version DEFAULT v1,
		serialNumber			CertificateSerialNumber,
		signature				AlgorithmIdentifier,
		issuer					Name,
		validity				Validity,
		subject					Name,
		subjectPublicKeyInfo	SubjectPublicKeyInfo,
		issuerUniqueID	[1]		IMPLICIT UniqueIdentifier OPTIONAL,
							-- If present, version shall be v2 or v3
		subjectUniqueID	[2]	IMPLICIT UniqueIdentifier OPTIONAL,
							-- If present, version shall be v2 or v3
		extensions		[3]	EXPLICIT Extensions OPTIONAL
							-- If present, version shall be v3	}
*/
		if (getSequence(&p, (int32)(end - p), &len) < 0) {
			matrixStrDebugMsg("ASN sequence parse error\n", NULL);
			return -1;
		}
		certEnd = p + len;
		certLen = (int32)(certEnd - certStart);

/*
		Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
*/
		if (getExplicitVersion(&p, (int32)(end - p), 0, &cert->version) < 0) {
			matrixStrDebugMsg("ASN version parse error\n", NULL);
			return -1;
		}
		if (cert->version != 2) {
			matrixIntDebugMsg("Warning: non-v3 certificate version: %d\n",
			cert->version);
		}
/*
		CertificateSerialNumber  ::=  INTEGER
*/
		if (getSerialNum(pool, &p, (int32)(end - p), &cert->serialNumber,
				&cert->serialNumberLen) < 0) {
			matrixStrDebugMsg("ASN serial number parse error\n", NULL);
			return -1;
		}
/*
		AlgorithmIdentifier  ::=  SEQUENCE  {
		algorithm				OBJECT IDENTIFIER,
		parameters				ANY DEFINED BY algorithm OPTIONAL }
*/
		if (getAlgorithmIdentifier(&p, (int32)(end - p),
				&cert->certAlgorithm, 0) < 0) {
			return -1;
		}
/*
		Name ::= CHOICE {
		RDNSequence }

		RDNSequence ::= SEQUENCE OF RelativeDistinguishedName

		RelativeDistinguishedName ::= SET OF AttributeTypeAndValue

		AttributeTypeAndValue ::= SEQUENCE {
		type	AttributeType,
		value	AttributeValue }

		AttributeType ::= OBJECT IDENTIFIER

		AttributeValue ::= ANY DEFINED BY AttributeType
*/
		if (getDNAttributes(pool, &p, (int32)(end - p), &cert->issuer) < 0) {
			return -1;
		}
/*
		Validity ::= SEQUENCE {
		notBefore	Time,
		notAfter	Time	}
*/
		if (getValidity(pool, &p, (int32)(end - p), &cert->notBefore,
				&cert->notAfter) < 0) {
			return -1;
		}
/*
		Subject DN
*/
		if (getDNAttributes(pool, &p, (int32)(end - p), &cert->subject) < 0) {
			return -1;
		}
/*
		SubjectPublicKeyInfo  ::=  SEQUENCE  {
		algorithm			AlgorithmIdentifier,
		subjectPublicKey	BIT STRING	}
*/
		if (getSequence(&p, (int32)(end - p), &len) < 0) {
			return -1;
		}
		if (getAlgorithmIdentifier(&p, (int32)(end - p),
				&cert->pubKeyAlgorithm, 1) < 0) {
			return -1;
		}
		if (getPubKey(pool, &p, (int32)(end - p), &cert->publicKey) < 0) {
			return -1;
		}
/*
		As the next three values are optional, we can do a specific test here
*/
		if (*p != (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
			if (getImplicitBitString(pool, &p, (int32)(end - p), IMPLICIT_ISSUER_ID,
					&cert->uniqueUserId, &cert->uniqueUserIdLen) < 0 ||
				getImplicitBitString(pool, &p, (int32)(end - p), IMPLICIT_SUBJECT_ID,
					&cert->uniqueSubjectId, &cert->uniqueSubjectIdLen) < 0 ||
				getExplicitExtensions(pool, &p, (int32)(end - p), EXPLICIT_EXTENSION,
					&cert->extensions) < 0) {
				matrixStrDebugMsg("There was an error parsing a certificate\n", NULL);
				matrixStrDebugMsg("extension.  This is likely caused by an\n", NULL);
				matrixStrDebugMsg("extension format that is not currently\n", NULL);
				matrixStrDebugMsg("recognized.  Please email [email protected]\n", NULL);
				matrixStrDebugMsg("to add support for the extension.\n\n", NULL);
				return -1;
			}
		}
/*
		This is the end of the cert.  Do a check here to be certain
*/
		if (certEnd != p) {
			return -1;
		}
/*
		Certificate signature info
*/
		if (getAlgorithmIdentifier(&p, (int32)(end - p),
				&cert->sigAlgorithm, 0) < 0) {
			return -1;
		}
/*
		Signature algorithm must match that specified in TBS cert
*/
		if (cert->certAlgorithm != cert->sigAlgorithm) {
			matrixStrDebugMsg("Parse error: mismatched signature type\n", NULL);
			return -1; 
		}
/*
		Compute the hash of the cert here for CA validation
*/
		if (cert->certAlgorithm == OID_RSA_MD5) {
			matrixMd5Init(&md5Ctx);
			matrixMd5Update(&md5Ctx, certStart, certLen);
			matrixMd5Final(&md5Ctx, cert->sigHash);
		} else if (cert->certAlgorithm == OID_RSA_SHA1) {
			matrixSha1Init(&sha1Ctx);
			matrixSha1Update(&sha1Ctx, certStart, certLen);
			matrixSha1Final(&sha1Ctx, cert->sigHash);
		}
#ifdef USE_MD2
		else if (cert->certAlgorithm == OID_RSA_MD2) {
			matrixMd2Init(&md2Ctx);
			matrixMd2Update(&md2Ctx, certStart, certLen);
			matrixMd2Final(&md2Ctx, cert->sigHash);
		}
#endif /* USE_MD2 */

		if (getSignature(pool, &p, (int32)(end - p), &cert->signature,
				&cert->signatureLen) < 0) {
			return -1;
		}
/*
		The ability to parse additional chained certs is a PKI product
		feature addition.  Chaining in MatrixSSL is handled internally.
*/
		if (p != end) {
			cert->next = psMalloc(pool, sizeof(sslRsaCert_t));
			cert = cert->next;
			memset(cert, '\0', sizeof(sslRsaCert_t));
		} else {
			parsing = 0;
		}
	}
		
	return (int32)(p - pp);
}
Example #4
0
 virtual void printAlgorithmConfiguration(void) const {PRINT_FORMATTED_INFO(getAlgorithmIdentifier() << " configuration:");};