⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 x509.c

📁 PeerSec Networks MatrixSSL?is an embedded SSL implementation designed for small footprint applicatio
💻 C
📖 第 1 页 / 共 3 页
字号:
			if (*p++ != 1) {
				matrixStrDebugMsg("Error parsing cert extension\n", NULL);
				return -1;
			}
			if (*p++ > 0) {
				critical = 1;
			}
		}
		if (extEnd - p < 1 || (*p++ != ASN_OCTET_STRING) ||
				asnParseLength(&p, (int32)(extEnd - p), &len) < 0 || 
				extEnd - p < len) {
			matrixStrDebugMsg("Expecting OCTET STRING in ext parse\n", NULL);
			return -1;
		}

		switch (noid) {
/*
			 BasicConstraints ::= SEQUENCE {
				cA						BOOLEAN DEFAULT FALSE,
				pathLenConstraint		INTEGER (0..MAX) OPTIONAL }
*/
			case EXT_BASIC_CONSTRAINTS:
				if (getSequence(&p, (int32)(extEnd - p), &len) < 0) {
					return -1;
				}
/*
				"This goes against PKIX guidelines but some CAs do it and some
				software requires this to avoid interpreting an end user
				certificate as a CA."
					- OpenSSL certificate configuration doc

				basicConstraints=CA:FALSE
*/
				if (len == 0) {
					break;
				}
				if (extEnd - p < 3) {
					return -1;
				}
				if (*p++ != ASN_BOOLEAN) {
					return -1;
				}
				if (*p++ != 1) {
					return -1;
				}
				extensions->bc.ca = *p++;
/*
				Now need to check if there is a path constraint. Only makes
				sense if cA is true.  If it's missing, there is no limit to
				the cert path
*/
				if (*p == ASN_INTEGER) {
					if (getInteger(&p, (int32)(extEnd - p),
							&(extensions->bc.pathLenConstraint)) < 0) {
						return -1;
					}
				} else {
					extensions->bc.pathLenConstraint = -1;
				}
				break;
			case EXT_ALT_SUBJECT_NAME:
				if (getSequence(&p, (int32)(extEnd - p), &len) < 0) {
					return -1;
				}
/*
				Looking only for DNS, URI, and email here to support
				FQDN for Web clients

				FUTURE:  Support all subject alt name members
				GeneralName ::= CHOICE {
					otherName						[0]		OtherName,
					rfc822Name						[1]		IA5String,
					dNSName							[2]		IA5String,
					x400Address						[3]		ORAddress,
					directoryName					[4]		Name,
					ediPartyName					[5]		EDIPartyName,
					uniformResourceIdentifier		[6]		IA5String,
					iPAddress						[7]		OCTET STRING,
					registeredID					[8]		OBJECT IDENTIFIER }
*/
				while (len > 0) {
					if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) {
						p++;
						tmpLen = *p++;
						if (extEnd - p < tmpLen) {
							return -1;
						}
						extensions->san.dns = psMalloc(pool, tmpLen + 1);
						if (extensions->san.dns == NULL) {
							return -8; /* SSL_MEM_ERROR */
						}
						memset(extensions->san.dns, 0x0, tmpLen + 1);
						memcpy(extensions->san.dns, p, tmpLen);
					} else if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 6)) {
						p++;
						tmpLen = *p++;
						if (extEnd - p < tmpLen) {
							return -1;
						}
						extensions->san.uri = psMalloc(pool, tmpLen + 1);
						if (extensions->san.uri == NULL) {
							return -8; /* SSL_MEM_ERROR */
						}
						memset(extensions->san.uri, 0x0, tmpLen + 1);
						memcpy(extensions->san.uri, p, tmpLen);
					} else if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 1)) {
						p++;
						tmpLen = *p++;
						if (extEnd - p < tmpLen) {
							return -1;
						}
						extensions->san.email = psMalloc(pool, tmpLen + 1);
						if (extensions->san.email == NULL) {
							return -8; /* SSL_MEM_ERROR */
						}
						memset(extensions->san.email, 0x0, tmpLen + 1);
						memcpy(extensions->san.email, p, tmpLen);
					} else {
						matrixStrDebugMsg("Unsupported subjectAltName type.n",
							NULL);
						p++;
						tmpLen = *p++;
						if (extEnd - p < tmpLen) {
							return -1;
						}
					}
					p = p + tmpLen;
					len -= tmpLen + 2; /* the magic 2 is the type and length */
				}
				break;
#ifdef USE_FULL_CERT_PARSE
			case EXT_AUTH_KEY_ID:
/*
				AuthorityKeyIdentifier ::= SEQUENCE {
				keyIdentifier				[0] KeyIdentifier			OPTIONAL,
				authorityCertIssuer			[1] GeneralNames			OPTIONAL,
				authorityCertSerialNumber	[2] CertificateSerialNumber	OPTIONAL }

				KeyIdentifier ::= OCTET STRING
*/
				if (getSequence(&p, (int32)(extEnd - p), &len) < 0 || len < 1) {
					return -1;
				}
/*
				All memebers are optional
*/
				if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 0)) {
					p++;
					if (asnParseLength(&p, (int32)(extEnd - p), 
							&extensions->ak.keyLen) < 0 ||
							extEnd - p < extensions->ak.keyLen) {
						return -1;
					}
					extensions->ak.keyId = psMalloc(pool, extensions->ak.keyLen);
					if (extensions->ak.keyId == NULL) {
						return -8; /* SSL_MEM_ERROR */
					}
					memcpy(extensions->ak.keyId, p, extensions->ak.keyLen);
					p = p + extensions->ak.keyLen;
				}
				if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) {
					p++;
					if (asnParseLength(&p, (int32)(extEnd - p), &len) < 0 ||
							len < 1 || extEnd - p < len) {
						return -1;
					}
					if ((*p ^ ASN_CONTEXT_SPECIFIC ^ ASN_CONSTRUCTED) != 4) {
/*
						FUTURE: support other name types
						We are just dealing with DN formats here
*/
						matrixIntDebugMsg("Error auth key-id name type: %d\n",
							*p ^ ASN_CONTEXT_SPECIFIC ^ ASN_CONSTRUCTED);
						return -1;
					}
					p++;
					if (asnParseLength(&p, (int32)(extEnd - p), &len) < 0 || 
							extEnd - p < len) {
						return -1;
					}
					if (getDNAttributes(pool, &p, (int32)(extEnd - p),
							&(extensions->ak.attribs)) < 0) {
						return -1;
					}
				}
				if ((*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) ||
						(*p == ASN_INTEGER)){
/*
					Treat as a serial number (not a native INTEGER)
*/
					if (getSerialNum(pool, &p, (int32)(extEnd - p),
							&(extensions->ak.serialNum), &len) < 0) {
						return -1;
					}
					extensions->ak.serialNumLen = len;
				}
				break;

			case EXT_KEY_USAGE:
/*
				KeyUsage ::= BIT STRING {
					digitalSignature		(0),
					nonRepudiation			(1),
					keyEncipherment			(2),
					dataEncipherment		(3),
					keyAgreement			(4),
					keyCertSign				(5),

					cRLSign					(6),
					encipherOnly			(7),
					decipherOnly			(8) }
*/
				if (*p++ != ASN_BIT_STRING) {
					return -1;
				}
				if (asnParseLength(&p, (int32)(extEnd - p), &len) < 0 || 
						extEnd - p < len) {
					return -1;
				}
				if (len != 2) {
					return -1;
				}
/*
				Assure all unused bits are 0 and store away
*/
				extensions->keyUsage = (*(p + 1)) & ~((1 << *p) -1);
				p = p + len;
				break;
			case EXT_SUBJ_KEY_ID:
/*
				The value of the subject key identifier MUST be the value
				placed in the key identifier field of the Auth Key Identifier
				extension of certificates issued by the subject of
				this certificate.
*/
				if (*p++ != ASN_OCTET_STRING || asnParseLength(&p,
						(int32)(extEnd - p), &(extensions->sk.len)) < 0 ||
						extEnd - p < extensions->sk.len) {
					return -1;
				}
				extensions->sk.id = psMalloc(pool, extensions->sk.len);
				if (extensions->sk.id == NULL) {
					return -8; /* SSL_MEM_ERROR */
				}
				memcpy(extensions->sk.id, p, extensions->sk.len);
				p = p + extensions->sk.len;
				break;
#endif /* USE_FULL_CERT_PARSE */
/*
			Unsupported or skipping because USE_FULL_CERT_PARSE is undefined
*/
			default:
				if (critical) {
/*
					SPEC DIFFERENCE:  Ignoring an unrecognized critical
					extension.  The specification dictates an error should
					occur, but real-world experience has shown this is not
					a realistic or desirable action.  Also, no other SSL
					implementations have been found to error in this case.
					It is NOT a security risk in an RSA authenticaion sense.
*/
					matrixStrDebugMsg("Unknown critical ext encountered\n",
						NULL);
				}
				p++;
/*
				Skip over based on the length reported from the ASN_SEQUENCE
				surrounding the entire extension.  It is not a guarantee that
				the value of the extension itself will contain it's own length.
*/
				p = p + (fullExtLen - (p - extStart));
				break;
		}
	}
	*pp = p;
	return 0;
}

/******************************************************************************/
/*
	Walk through the certificate chain and validate it.  Return the final
	member of the chain as the subjectCert that can then be validated against
	the CAs.  The subjectCert points into the chain param (no need to free)
*/
int32 matrixX509ValidateCertChain(psPool_t *pool, sslRsaCert_t *chain, 
							sslRsaCert_t **subjectCert, int32 *valid)
{
	sslRsaCert_t	*ic;

	*subjectCert = chain;
	*valid = 1;
	while ((*subjectCert)->next != NULL) {
		ic = (*subjectCert)->next;
		if (matrixX509ValidateCertInternal(pool, *subjectCert, ic, 1) < 0) {
			*valid = -1;
			return -1;
		}
/*
		If any portion is invalid, it's all invalid
*/
		if ((*subjectCert)->valid != 1) {
			*valid = -1;
		}
		*subjectCert = (*subjectCert)->next;
	}
	return 0;
}

/******************************************************************************/
/*
	A signature validation for certificates.  -1 return is an error.  The success
	of the validation is returned in the 'valid' param of the subjectCert.
	1 if the issuerCert	signed the subject cert. -1 if not
*/
int32 matrixX509ValidateCert(psPool_t *pool, sslRsaCert_t *subjectCert, 
						   sslRsaCert_t *issuerCert, int32 *valid)
{
	if (matrixX509ValidateCertInternal(pool, subjectCert, issuerCert, 0) < 0) {
		*valid = -1;
		return -1;
	}
	*valid = subjectCert->valid;
	return 0;
}

static int32 matrixX509ValidateCertInternal(psPool_t *pool, sslRsaCert_t *subjectCert, 
						   sslRsaCert_t *issuerCert, int32 chain)
{
	sslRsaCert_t	*ic;
	unsigned char	sigOut[10 + SSL_SHA1_HASH_SIZE + 5];	/* See below */
	int32			sigLen;

	subjectCert->valid = -1;
/*
	Supporting a one level chain or a self-signed cert.  If the issuer
	is NULL, the self-signed test is done.
*/
	if (issuerCert == NULL) {
		matrixStrDebugMsg("Warning:  No CA to validate cert with\n", NULL);
		matrixStrDebugMsg("\tPerforming self-signed CA test\n", NULL);
		ic = subjectCert;
	} else {
		ic = issuerCert;
	}
/*
	Path confirmation.	If this is a chain verification, do not allow
	any holes in the path.  Error out if issuer does not have CA permissions
	or if hashes do not match anywhere along the way.
*/
	while (ic) {
		if (subjectCert != ic) {
/*
			Certificate authority contraint32 only available in version 3 certs
*/
			if ((ic->version > 1) && (ic->extensions.bc.ca <= 0)) {
				if (chain) {
					return -1;
				}
				ic = ic->next;
				continue;
			}
/*
			Use sha1 hash of issuer fields computed at parse time to compare
*/
			if (memcmp(subjectCert->issuer.hash, ic->subject.hash,
					SSL_SHA1_HASH_SIZE) != 0) {
				if (chain) {
					return -1;
				}
				ic = ic->next;
				continue;
			}
		}
/*
		Signature confirmation
		The sigLen is the ASN.1 size in bytes for encoding the hash.
		The magic 10 is comprised of the SEQUENCE and ALGORITHM ID overhead.
		The magic 8 and 5 are the OID lengths of the corresponding algorithm.
		NOTE: if sigLen is modified, above sigOut static size must be changed
*/
		if (subjectCert->sigAlgorithm ==  OID_RSA_MD5 ||
				subjectCert->sigAlgorithm == OID_RSA_MD2) {
			sigLen = 10 + SSL_MD5_HASH_SIZE + 8;	/* See above */
		} else if (subjectCert->sigAlgorithm == OID_RSA_SHA1) {
			sigLen = 10 + SSL_SHA1_HASH_SIZE + 5;	/* See above */
		} else {
			matrixStrDebugMsg("Unsupported signature algorithm\n", NULL);
			return -1;
		}
		sslAssert(sigLen <= sizeof(sigOut));
		matrixRsaDecryptPub(pool, &(ic->publicKey), subjectCert->signature,
			subjectCert->signatureLen, sigOut, sigLen);
/*
		If this is a chain test, fail on any gaps in the chain
*/
		if (psAsnConfirmSignature(subjectCert->sigHash, sigOut, sigLen) < 0) {
			if (chain) {
				return -1;
			}
			ic = ic->next;
			continue;
		}
/*
		Fall through to here only if passed signature check.
*/
		subjectCert->valid = 1;
		break;
	}
	return 0;
}

/******************************************************************************/
/*
	Calls a user defined callback to allow for manual validation of the
	certificate.
*/
int32 matrixX509UserValidator(psPool_t *pool, sslRsaCert_t *subjectCert,
			int32 (*certValidator)(sslCertInfo_t *t, void *arg), void *arg)
{
	sslCertInfo_t	*cert, *current, *next;
	int32			rc;

	if (certValidator == NULL) {
		return 0;
	}
/*
	Pass the entire certificate chain to the user callback.
*/
	current = cert = psMalloc(pool, sizeof(sslCertInfo_t));
	if (current == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memset(cert, 0x0, sizeof(sslCertInfo_t));
	while (subjectCert) {
		
		current->issuer.commonName = subjectCert->issuer.commonName;
		current->issuer.country = subjectCert->issuer.country;
		current->issuer.locality = subjectCert->issuer.locality;
		current->issuer.organization = subjectCert->issuer.organization;
		current->issuer.orgUnit = subjectCert->issuer.orgUnit;
		current->issuer.state = subjectCert->issuer.state;

		current->subject.commonName = subjectCert->subject.commonName;
		current->subject.country = subjectCert->subject.country;
		current->subject.locality = subjectCert->subject.locality;
		current->subject.organization = subjectCert->subject.organization;
		current->subject.orgUnit = subjectCert->subject.orgUnit;
		current->subject.state = subjectCert->subject.state;

		current->serialNumber = subjectCert->serialNumber;
		current->serialNumberLen = subjectCert->serialNumberLen;
		current->verified = subjectCert->valid;
		current->notBefore = subjectCert->notBefore;
		current->notAfter = subjectCert->notAfter;

		current->subjectAltName.dns = (char*)subjectCert->extensions.san.dns;
		current->subjectAltName.uri = (char*)subjectCert->extensions.san.uri;
		current->subjectAltName.email = (char*)subjectCert->extensions.san.email;
	
		if (subjectCert->certAlgorithm == OID_RSA_MD5 ||
				subjectCert->certAlgorithm == OID_RSA_MD2) {
			current->sigHashLen = SSL_MD5_HASH_SIZE;
		} else if (subjectCert->certAlgorithm == OID_RSA_SHA1) {
			current->sigHashLen = SSL_SHA1_HASH_SIZE;
		}
		current->sigHash = (char*)subjectCert->sigHash;
		if (subjectCert->next) {
			next = psMalloc(pool, sizeof(sslCertInfo_t));
			if (next == NULL) {
				while (cert) {
					next = cert->next;
					psFree(cert);
					cert = next;
				}
				return -8; /* SSL_MEM_ERROR */
			}
			memset(next, 0x0, sizeof(sslCertInfo_t));
			current->next = next;
			current = next;
		}
		subjectCert = subjectCert->next;
	}
/*
	The user callback
*/
	rc = certValidator(cert, arg);
/*
	Free the chain
*/
	while (cert) {
		next = cert->next;
		psFree(cert);
		cert = next;
	}
	return rc;
}
#endif /* USE_X509 */
#endif /* USE_RSA */

/******************************************************************************/


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -