// Set the private key int CertManager::SetPrivateKey(const x509& key) { privateKey_.allocate(key.get_length()); privateKey_.assign(key.get_buffer(), key.get_length()); // set key type if (x509* cert = list_.front()) { TaoCrypt::Source source(cert->get_buffer(), cert->get_length()); TaoCrypt::CertDecoder cd(source, false); cd.DecodeToKey(); if (int err = cd.GetError().What()) return err; if (cd.GetKeyType() == TaoCrypt::RSAk) keyType_ = rsa_sa_algo; else keyType_ = dsa_sa_algo; size_t iSz = strlen(cd.GetIssuer()) + 1; size_t sSz = strlen(cd.GetCommonName()) + 1; ASN1_STRING beforeDate, afterDate; beforeDate.data= (unsigned char *) cd.GetBeforeDate(); beforeDate.type= cd.GetBeforeDateType(); beforeDate.length= strlen((char *) beforeDate.data) + 1; afterDate.data= (unsigned char *) cd.GetAfterDate(); afterDate.type= cd.GetAfterDateType(); afterDate.length= strlen((char *) afterDate.data) + 1; selfX509_ = NEW_YS X509(cd.GetIssuer(), iSz, cd.GetCommonName(), sSz, &beforeDate, &afterDate); } return 0; }
// Validate the peer's certificate list, from root to peer (last to first) int CertManager::Validate() { CertList::reverse_iterator last = peerList_.rbegin(); size_t count = peerList_.size(); while ( count > 1 ) { TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length()); TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_); int err = cert.GetError().What(); if ( err ) return err; const TaoCrypt::PublicKey& key = cert.GetPublicKey(); signers_.push_back(NEW_YS TaoCrypt::Signer(key.GetKey(), key.size(), cert.GetCommonName(), cert.GetHash())); ++last; --count; } if (count) { // peer's is at the front TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length()); TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_); int err = cert.GetError().What(); if ( err && err != TaoCrypt::SIG_OTHER_E) return err; uint sz = cert.GetPublicKey().size(); peerPublicKey_.allocate(sz); peerPublicKey_.assign(cert.GetPublicKey().GetKey(), sz); if (cert.GetKeyType() == TaoCrypt::RSAk) peerKeyType_ = rsa_sa_algo; else peerKeyType_ = dsa_sa_algo; size_t iSz = strlen(cert.GetIssuer()) + 1; size_t sSz = strlen(cert.GetCommonName()) + 1; int bSz = (int)strlen(cert.GetBeforeDate()) + 1; int aSz = (int)strlen(cert.GetAfterDate()) + 1; peerX509_ = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(), sSz, cert.GetBeforeDate(), bSz, cert.GetAfterDate(), aSz); if (err == TaoCrypt::SIG_OTHER_E && verifyCallback_) { X509_STORE_CTX store; store.error = err; store.error_depth = static_cast<int>(count) - 1; store.current_cert = peerX509_; int ok = verifyCallback_(0, &store); if (ok) return 0; } if (err == TaoCrypt::SIG_OTHER_E) return err; } return 0; }
IoObject *IoCertificate_attributes(IoCertificate *self, IoObject *locals, IoMessage *m) { IoObject *map = IoObject_new(IoObject_state(self)); const EVP_PKEY *pkey = X509_extract_key(X509(self)); int i; for(i = 0; i < EVP_PKEY_get_attr_count(pkey); i++) { IoList *list = IoList_new(IoObject_state(self)); X509_ATTRIBUTE *attr = EVP_PKEY_get_attr(pkey, i); const char *key = (const char *)OBJ_nid2ln(OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr))); int j; for(j = 0; j < X509_ATTRIBUTE_count(attr); j++) { ASN1_TYPE *attrType = X509_ATTRIBUTE_get0_type(attr, j); ASN1_OBJECT *attrData = X509_ATTRIBUTE_get0_data(attr, j, attrType->type, NULL); //consider switching on attrType instead; //really, that would be wiser, so that dates, //numbers, etc can be happy /* switch(attrType->type) { case V_ASN1_OCTET_STRING: ... */ int len = i2t_ASN1_OBJECT(NULL, 0, attrData); char *value = calloc(len, sizeof(char)); i2t_ASN1_OBJECT(value, len, attrData); IoList_rawAppend_(list, IoSeq_newWithCString_(IoObject_state(self), value)); } IoObject_setSlot_to_(map, IOSYMBOL(key), list); } return map; }
void IoCertificate_free(IoCertificate *self) { if(SHOULDFREE(self)) { X509_free(X509(self)); } free(CERTIFICATE(self)); }
IoObject *IoCertificate_extensions(IoCertificate *self, IoObject *locals, IoMessage *m) { IoObject *map = IoObject_new(IoObject_state(self)); int i; for(i = 0; i < X509_get_ext_count(X509(self)); i++) { IoObject *ioext = IoObject_new(IoObject_state(self)); X509_EXTENSION *ext = X509_get_ext(X509(self), i); const char *key = (const char *)OBJ_nid2ln(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); const char *value = (const char *)ASN1_STRING_data(X509_EXTENSION_get_data(ext)); int isCritical = X509_EXTENSION_get_critical(ext); IoObject_setSlot_to_(ioext, IOSYMBOL("value"), IoSeq_newWithCString_(IoObject_state(self), value)); IoObject_setSlot_to_(ioext, IOSYMBOL("isCritical"), IONUMBER(isCritical)); IoObject_setSlot_to_(map, IOSYMBOL(key), ioext); } return map; }
X509 getX509(const char* file) { ::X509* ret = nullptr; FILE* f = dcpp_fopen(file, "r"); if (f) { PEM_read_X509(f, &ret, nullptr, nullptr); fclose(f); } return X509(ret); }
// Store OpenSSL type peer's cert void CertManager::setPeerX509(X509* x) { if (x == 0) return; X509_NAME* issuer = x->GetIssuer(); X509_NAME* subject = x->GetSubject(); ASN1_STRING* before = x->GetBefore(); ASN1_STRING* after = x->GetAfter(); peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(), subject->GetName(), subject->GetLength(), before, after); }
// Store OpenSSL type peer's cert void CertManager::setPeerX509(X509* x) { assert(peerX509_ == 0); if (x == 0) return; X509_NAME* issuer = x->GetIssuer(); X509_NAME* subject = x->GetSubject(); ASN1_STRING* before = x->GetBefore(); ASN1_STRING* after = x->GetAfter(); peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(), subject->GetName(), subject->GetLength(), (const char*) before->data, before->length, (const char*) after->data, after->length); }
X509* X509_Copy(X509 *x) { if (x == 0) return NULL; X509_NAME* issuer = x->GetIssuer(); X509_NAME* subject = x->GetSubject(); ASN1_TIME* before = x->GetBefore(); ASN1_TIME* after = x->GetAfter(); X509 *newX509 = NEW_YS X509(issuer->GetName(), issuer->GetLength(), subject->GetName(), subject->GetLength(), before, after, issuer->GetCnPosition(), issuer->GetCnLength(), subject->GetCnPosition(), subject->GetCnLength()); return newX509; }
X509* PEM_read_X509(FILE *fp, X509 *x, pem_password_cb cb, void *u) { if (fp == NULL) return NULL; // Get x509 handle and encryption information x509* ptr = PemToDer(fp, Cert); if (!ptr) return NULL; // Now decode x509 object. TaoCrypt::SignerList signers; TaoCrypt::Source source(ptr->get_buffer(), ptr->get_length()); TaoCrypt::CertDecoder cert(source, true, &signers, true, TaoCrypt::CertDecoder::CA); if (cert.GetError().What()) { ysDelete(ptr); return NULL; } // Ok. Now create X509 object. size_t iSz = strlen(cert.GetIssuer()) + 1; size_t sSz = strlen(cert.GetCommonName()) + 1; ASN1_STRING beforeDate, afterDate; beforeDate.data = (unsigned char *) cert.GetBeforeDate(); beforeDate.type = cert.GetBeforeDateType(); beforeDate.length = strlen((char *) beforeDate.data) + 1; afterDate.data = (unsigned char *) cert.GetAfterDate(); afterDate.type = cert.GetAfterDateType(); afterDate.length = strlen((char *) afterDate.data) + 1; X509 *thisX509 = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(), sSz, &beforeDate, &afterDate, cert.GetIssuerCnStart(), cert.GetIssuerCnLength(), cert.GetSubjectCnStart(), cert.GetSubjectCnLength()); ysDelete(ptr); return thisX509; }
IoObject *IoCertificate_notAfter(IoCertificate *self, IoObject *locals, IoMessage *m) { return IoCertificate_asnTimeToDate(self, X509_get_notAfter(X509(self))); }
IoObject *IoCertificate_serialNumber(IoCertificate *self, IoObject *locals, IoMessage *m) { return IONUMBER(ASN1_INTEGER_get(X509_get_serialNumber(X509(self)))); }
IoObject *IoCertificate_subjectName(IoCertificate *self, IoObject *locals, IoMessage *m) { return IoCertificate_nameToObject(self, X509_get_subject_name(X509(self))); }
IoCertificate *IoCertificate_version(IoCertificate *self, IoObject *locals, IoMessage *m) { return IONUMBER(X509_get_version(X509(self)) + 1); }