00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "qca_cert.h"
00023
00024 #include "qca_publickey.h"
00025 #include "qcaprovider.h"
00026
00027 #include <QTextStream>
00028 #include <QFile>
00029 #include <QUrl>
00030
00031 #include <stdlib.h>
00032
00033 namespace QCA {
00034
00035 Provider::Context *getContext(const QString &type, const QString &provider);
00036 Provider::Context *getContext(const QString &type, Provider *p);
00037
00038
00039 bool stringToFile(const QString &fileName, const QString &content);
00040 bool stringFromFile(const QString &fileName, QString *s);
00041 bool arrayToFile(const QString &fileName, const QByteArray &content);
00042 bool arrayFromFile(const QString &fileName, QByteArray *a);
00043 bool ask_passphrase(const QString &fname, void *ptr, SecureArray *answer);
00044 ProviderList allProviders();
00045 Provider *providerForName(const QString &name);
00046 bool use_asker_fallback(ConvertResult r);
00047
00048
00049 static bool get_pkcs12_der(const QByteArray &der, const QString &fileName, void *ptr, const SecureArray &passphrase, ConvertResult *result, const QString &provider, QString *name, CertificateChain *chain, PrivateKey *key)
00050 {
00051 QString _name;
00052 QList<CertContext*> list;
00053 PKeyContext *kc = 0;
00054
00055 PKCS12Context *pix = static_cast<PKCS12Context *>(getContext("pkcs12", provider));
00056 ConvertResult r = pix->fromPKCS12(der, passphrase, &_name, &list, &kc);
00057
00058
00059 if(use_asker_fallback(r) && passphrase.isEmpty())
00060 {
00061 SecureArray pass;
00062 if(ask_passphrase(fileName, ptr, &pass))
00063 r = pix->fromPKCS12(der, pass, &_name, &list, &kc);
00064 }
00065 delete pix;
00066
00067 if(result)
00068 *result = r;
00069
00070 if(r == ConvertGood)
00071 {
00072 *name = _name;
00073 for(int n = 0; n < list.count(); ++n)
00074 {
00075 Certificate cert;
00076 cert.change(list[n]);
00077 chain->append(cert);
00078 }
00079 key->change(kc);
00080 return true;
00081 }
00082 return false;
00083 }
00084
00085 static CertificateInfo orderedToMap(const CertificateInfoOrdered &info)
00086 {
00087 CertificateInfo out;
00088
00089
00090 for(int n = 0; n < info.count(); ++n)
00091 {
00092 const CertificateInfoPair &i = info[n];
00093 if(i.type().known() != EmailLegacy)
00094 out.insert(i.type(), i.value());
00095 }
00096
00097
00098 for(int n = 0; n < info.count(); ++n)
00099 {
00100 const CertificateInfoPair &i = info[n];
00101 if(i.type().known() == EmailLegacy)
00102 {
00103
00104 QList<QString> emails = out.values(Email);
00105 if(!emails.contains(i.value()))
00106 out.insert(Email, i.value());
00107 }
00108 }
00109
00110 return out;
00111 }
00112
00113 static void moveMapValues(CertificateInfo *from, CertificateInfoOrdered *to, const CertificateInfoType &type)
00114 {
00115 QList<QString> values = from->values(type);
00116 from->remove(type);
00117
00118
00119
00120 for(int n = values.count() - 1; n >= 0; --n)
00121 to->append(CertificateInfoPair(type, values[n]));
00122 }
00123
00124 static CertificateInfoOrdered mapToOrdered(const CertificateInfo &info)
00125 {
00126 CertificateInfo in = info;
00127 CertificateInfoOrdered out;
00128
00129
00130 moveMapValues(&in, &out, CommonName);
00131 moveMapValues(&in, &out, Country);
00132 moveMapValues(&in, &out, Locality);
00133 moveMapValues(&in, &out, State);
00134 moveMapValues(&in, &out, Organization);
00135 moveMapValues(&in, &out, OrganizationalUnit);
00136 moveMapValues(&in, &out, Email);
00137 moveMapValues(&in, &out, URI);
00138 moveMapValues(&in, &out, DNS);
00139 moveMapValues(&in, &out, IPAddress);
00140 moveMapValues(&in, &out, XMPP);
00141
00142
00143 QList<CertificateInfoType> typesLeft = in.keys();
00144
00145
00146 QList<CertificateInfoType> types;
00147 for(int n = 0; n < typesLeft.count(); ++n)
00148 {
00149 if(!types.contains(typesLeft[n]))
00150 types += typesLeft[n];
00151 }
00152
00153
00154 for(int n = 0; n < types.count(); ++n)
00155 moveMapValues(&in, &out, types[n]);
00156
00157 Q_ASSERT(in.isEmpty());
00158
00159 return out;
00160 }
00161
00162
00163
00164
00165 static const char CommonName_id[] = "2.5.4.3";
00166 static const char Email_id[] = "GeneralName.rfc822Name";
00167 static const char EmailLegacy_id[] = "1.2.840.113549.1.9.1";
00168 static const char Organization_id[] = "2.5.4.10";
00169 static const char OrganizationalUnit_id[] = "2.5.4.11";
00170 static const char Locality_id[] = "2.5.4.7";
00171 static const char IncorporationLocality_id[] = "1.3.6.1.4.1.311.60.2.1.1";
00172 static const char State_id[] = "2.5.4.8";
00173 static const char IncorporationState_id[] = "1.3.6.1.4.1.311.60.2.1.2";
00174 static const char Country_id[] = "2.5.4.6";
00175 static const char IncorporationCountry_id[] = "1.3.6.1.4.1.311.60.2.1.3";
00176 static const char URI_id[] = "GeneralName.uniformResourceIdentifier";
00177 static const char DNS_id[] = "GeneralName.dNSName";
00178 static const char IPAddress_id[] = "GeneralName.iPAddress";
00179 static const char XMPP_id[] = "1.3.6.1.5.5.7.8.5";
00180
00181 static const char DigitalSignature_id[] = "KeyUsage.digitalSignature";
00182 static const char NonRepudiation_id[] = "KeyUsage.nonRepudiation";
00183 static const char KeyEncipherment_id[] = "KeyUsage.keyEncipherment";
00184 static const char DataEncipherment_id[] = "KeyUsage.dataEncipherment";
00185 static const char KeyAgreement_id[] = "KeyUsage.keyAgreement";
00186 static const char KeyCertificateSign_id[] = "KeyUsage.keyCertSign";
00187 static const char CRLSign_id[] = "KeyUsage.crlSign";
00188 static const char EncipherOnly_id[] = "KeyUsage.encipherOnly";
00189 static const char DecipherOnly_id[] = "KeyUsage.decipherOnly";
00190 static const char ServerAuth_id[] = "1.3.6.1.5.5.7.3.1";
00191 static const char ClientAuth_id[] = "1.3.6.1.5.5.7.3.2";
00192 static const char CodeSigning_id[] = "1.3.6.1.5.5.7.3.3";
00193 static const char EmailProtection_id[] = "1.3.6.1.5.5.7.3.4";
00194 static const char IPSecEndSystem_id[] = "1.3.6.1.5.5.7.3.5";
00195 static const char IPSecTunnel_id[] = "1.3.6.1.5.5.7.3.6";
00196 static const char IPSecUser_id[] = "1.3.6.1.5.5.7.3.7";
00197 static const char TimeStamping_id[] = "1.3.6.1.5.5.7.3.8";
00198 static const char OCSPSigning_id[] = "1.3.6.1.5.5.7.3.9";
00199
00200 static QString knownToId(CertificateInfoTypeKnown k)
00201 {
00202 const char *out = 0;
00203 switch(k)
00204 {
00205 case CommonName: out = CommonName_id; break;
00206 case Email: out = Email_id; break;
00207 case EmailLegacy: out = EmailLegacy_id; break;
00208 case Organization: out = Organization_id; break;
00209 case OrganizationalUnit: out = OrganizationalUnit_id; break;
00210 case Locality: out = Locality_id; break;
00211 case IncorporationLocality: out = IncorporationLocality_id; break;
00212 case State: out = State_id; break;
00213 case IncorporationState: out = IncorporationState_id; break;
00214 case Country: out = Country_id; break;
00215 case IncorporationCountry: out = IncorporationCountry_id; break;
00216 case URI: out = URI_id; break;
00217 case DNS: out = DNS_id; break;
00218 case IPAddress: out = IPAddress_id; break;
00219 case XMPP: out = XMPP_id; break;
00220 }
00221 Q_ASSERT(out);
00222 if(!out)
00223 abort();
00224 return QString(out);
00225 }
00226
00227 static int idToKnown(const QString &id)
00228 {
00229 if(id == CommonName_id)
00230 return CommonName;
00231 else if(id == Email_id)
00232 return Email;
00233 else if(id == EmailLegacy_id)
00234 return EmailLegacy;
00235 else if(id == Organization_id)
00236 return Organization;
00237 else if(id == OrganizationalUnit_id)
00238 return OrganizationalUnit;
00239 else if(id == Locality_id)
00240 return Locality;
00241 else if(id == IncorporationLocality_id)
00242 return IncorporationLocality;
00243 else if(id == State_id)
00244 return State;
00245 else if(id == IncorporationState_id)
00246 return IncorporationState;
00247 else if(id == Country_id)
00248 return Country;
00249 else if(id == IncorporationCountry_id)
00250 return IncorporationCountry;
00251 else if(id == URI_id)
00252 return URI;
00253 else if(id == DNS_id)
00254 return DNS;
00255 else if(id == IPAddress_id)
00256 return IPAddress;
00257 else if(id == XMPP_id)
00258 return XMPP;
00259 else
00260 return -1;
00261 }
00262
00263 static CertificateInfoType::Section knownToSection(CertificateInfoTypeKnown k)
00264 {
00265 switch(k)
00266 {
00267 case CommonName:
00268 case EmailLegacy:
00269 case Organization:
00270 case OrganizationalUnit:
00271 case Locality:
00272 case IncorporationLocality:
00273 case State:
00274 case IncorporationState:
00275 case Country:
00276 case IncorporationCountry:
00277 return CertificateInfoType::DN;
00278 default:
00279 break;
00280 }
00281 return CertificateInfoType::AlternativeName;
00282 }
00283
00284 static const char *knownToShortName(CertificateInfoTypeKnown k)
00285 {
00286 switch(k)
00287 {
00288 case CommonName: return "CN";
00289 case Locality: return "L";
00290 case State: return "ST";
00291 case Organization: return "O";
00292 case OrganizationalUnit: return "OU";
00293 case Country: return "C";
00294 case EmailLegacy: return "emailAddress";
00295 default: break;
00296 }
00297 return 0;
00298 }
00299
00300 static QString constraintKnownToId(ConstraintTypeKnown k)
00301 {
00302 const char *out = 0;
00303 switch(k)
00304 {
00305 case DigitalSignature: out = DigitalSignature_id; break;
00306 case NonRepudiation: out = NonRepudiation_id; break;
00307 case KeyEncipherment: out = KeyEncipherment_id; break;
00308 case DataEncipherment: out = DataEncipherment_id; break;
00309 case KeyAgreement: out = KeyAgreement_id; break;
00310 case KeyCertificateSign: out = KeyCertificateSign_id; break;
00311 case CRLSign: out = CRLSign_id; break;
00312 case EncipherOnly: out = EncipherOnly_id; break;
00313 case DecipherOnly: out = DecipherOnly_id; break;
00314 case ServerAuth: out = ServerAuth_id; break;
00315 case ClientAuth: out = ClientAuth_id; break;
00316 case CodeSigning: out = CodeSigning_id; break;
00317 case EmailProtection: out = EmailProtection_id; break;
00318 case IPSecEndSystem: out = IPSecEndSystem_id; break;
00319 case IPSecTunnel: out = IPSecTunnel_id; break;
00320 case IPSecUser: out = IPSecUser_id; break;
00321 case TimeStamping: out = TimeStamping_id; break;
00322 case OCSPSigning: out = OCSPSigning_id; break;
00323 }
00324 Q_ASSERT(out);
00325 if(!out)
00326 abort();
00327 return QString(out);
00328 }
00329
00330 static int constraintIdToKnown(const QString &id)
00331 {
00332 if(id == DigitalSignature_id)
00333 return DigitalSignature;
00334 else if(id == NonRepudiation_id)
00335 return NonRepudiation;
00336 else if(id == KeyEncipherment_id)
00337 return KeyEncipherment;
00338 else if(id == DataEncipherment_id)
00339 return DataEncipherment;
00340 else if(id == KeyAgreement_id)
00341 return KeyAgreement;
00342 else if(id == KeyCertificateSign_id)
00343 return KeyCertificateSign;
00344 else if(id == CRLSign_id)
00345 return CRLSign;
00346 else if(id == EncipherOnly_id)
00347 return EncipherOnly;
00348 else if(id == DecipherOnly_id)
00349 return DecipherOnly;
00350 else if(id == ServerAuth_id)
00351 return ServerAuth;
00352 else if(id == ClientAuth_id)
00353 return ClientAuth;
00354 else if(id == CodeSigning_id)
00355 return CodeSigning;
00356 else if(id == EmailProtection_id)
00357 return EmailProtection;
00358 else if(id == IPSecEndSystem_id)
00359 return IPSecEndSystem;
00360 else if(id == IPSecTunnel_id)
00361 return IPSecTunnel;
00362 else if(id == IPSecUser_id)
00363 return IPSecUser;
00364 else if(id == TimeStamping_id)
00365 return TimeStamping;
00366 else if(id == OCSPSigning_id)
00367 return OCSPSigning;
00368 else
00369 return -1;
00370 }
00371
00372 static ConstraintType::Section constraintKnownToSection(ConstraintTypeKnown k)
00373 {
00374 switch(k)
00375 {
00376 case DigitalSignature:
00377 case NonRepudiation:
00378 case KeyEncipherment:
00379 case DataEncipherment:
00380 case KeyAgreement:
00381 case KeyCertificateSign:
00382 case CRLSign:
00383 case EncipherOnly:
00384 case DecipherOnly:
00385 return ConstraintType::KeyUsage;
00386 default:
00387 break;
00388 }
00389 return ConstraintType::ExtendedKeyUsage;
00390 }
00391
00392 static QString dnLabel(const CertificateInfoType &type)
00393 {
00394 const char *str = knownToShortName(type.known());
00395 if(str)
00396 return str;
00397
00398 QString id = type.id();
00399
00400 if(id[0].isDigit())
00401 return QString("OID.") + id;
00402
00403 return QString("qca.") + id;
00404 }
00405
00406 QString orderedToDNString(const CertificateInfoOrdered &in)
00407 {
00408 QStringList parts;
00409 foreach(const CertificateInfoPair &i, in)
00410 {
00411 if(i.type().section() != CertificateInfoType::DN)
00412 continue;
00413
00414 QString name = dnLabel(i.type());
00415 parts += name + '=' + i.value();
00416 }
00417 return parts.join(", ");
00418 }
00419
00420 CertificateInfoOrdered orderedDNOnly(const CertificateInfoOrdered &in)
00421 {
00422 CertificateInfoOrdered out;
00423 for(int n = 0; n < in.count(); ++n)
00424 {
00425 if(in[n].type().section() == CertificateInfoType::DN)
00426 out += in[n];
00427 }
00428 return out;
00429 }
00430
00431 static QString baseCertName(const CertificateInfo &info)
00432 {
00433 QString str = info.value(CommonName);
00434 if(str.isEmpty())
00435 {
00436 str = info.value(Organization);
00437 if(str.isEmpty())
00438 str = "Unnamed";
00439 }
00440 return str;
00441 }
00442
00443 static QList<int> findSameName(const QString &name, const QStringList &list)
00444 {
00445 QList<int> out;
00446 for(int n = 0; n < list.count(); ++n)
00447 {
00448 if(list[n] == name)
00449 out += n;
00450 }
00451 return out;
00452 }
00453
00454 static QString uniqueSubjectValue(const CertificateInfoType &type, const QList<int> items, const QList<Certificate> &certs, int i)
00455 {
00456 QStringList vals = certs[items[i]].subjectInfo().values(type);
00457 if(!vals.isEmpty())
00458 {
00459 foreach(int n, items)
00460 {
00461 if(n == items[i])
00462 continue;
00463
00464 QStringList other_vals = certs[n].subjectInfo().values(type);
00465 for(int k = 0; k < vals.count(); ++k)
00466 {
00467 if(other_vals.contains(vals[k]))
00468 {
00469 vals.removeAt(k);
00470 break;
00471 }
00472 }
00473
00474 if(vals.isEmpty())
00475 break;
00476 }
00477
00478 if(!vals.isEmpty())
00479 return vals[0];
00480 }
00481
00482 return QString();
00483 }
00484
00485 static QString uniqueIssuerName(const QList<int> items, const QList<Certificate> &certs, int i)
00486 {
00487 QString val = baseCertName(certs[items[i]].issuerInfo());
00488
00489 bool found = false;
00490 foreach(int n, items)
00491 {
00492 if(n == items[i])
00493 continue;
00494
00495 QString other_val = baseCertName(certs[n].issuerInfo());
00496 if(other_val == val)
00497 {
00498 found = true;
00499 break;
00500 }
00501 }
00502
00503 if(!found)
00504 return val;
00505
00506 return QString();
00507 }
00508
00509 static const char *constraintToString(const ConstraintType &type)
00510 {
00511 switch(type.known())
00512 {
00513 case DigitalSignature: return "DigitalSignature";
00514 case NonRepudiation: return "NonRepudiation";
00515 case KeyEncipherment: return "KeyEncipherment";
00516 case DataEncipherment: return "DataEncipherment";
00517 case KeyAgreement: return "KeyAgreement";
00518 case KeyCertificateSign: return "KeyCertificateSign";
00519 case CRLSign: return "CRLSign";
00520 case EncipherOnly: return "EncipherOnly";
00521 case DecipherOnly: return "DecipherOnly";
00522 case ServerAuth: return "ServerAuth";
00523 case ClientAuth: return "ClientAuth";
00524 case CodeSigning: return "CodeSigning";
00525 case EmailProtection: return "EmailProtection";
00526 case IPSecEndSystem: return "IPSecEndSystem";
00527 case IPSecTunnel: return "IPSecTunnel";
00528 case IPSecUser: return "IPSecUser";
00529 case TimeStamping: return "TimeStamping";
00530 case OCSPSigning: return "OCSPSigning";
00531 }
00532 return 0;
00533 }
00534
00535 static QString uniqueConstraintValue(const ConstraintType &type, const QList<int> items, const QList<Certificate> &certs, int i)
00536 {
00537 ConstraintType val = type;
00538 if(certs[items[i]].constraints().contains(type))
00539 {
00540 bool found = false;
00541 foreach(int n, items)
00542 {
00543 if(n == items[i])
00544 continue;
00545
00546 Constraints other_vals = certs[n].constraints();
00547 if(other_vals.contains(val))
00548 {
00549 found = true;
00550 break;
00551 }
00552 }
00553
00554 if(!found)
00555 return QString(constraintToString(val));
00556 }
00557
00558 return QString();
00559 }
00560
00561 static QString makeUniqueName(const QList<int> &items, const QStringList &list, const QList<Certificate> &certs, int i)
00562 {
00563 QString str, name;
00564
00565
00566 str = uniqueSubjectValue(Organization, items, certs, i);
00567 if(!str.isEmpty())
00568 {
00569 name = list[items[i]] + QString(" of ") + str;
00570 goto end;
00571 }
00572
00573
00574 str = uniqueSubjectValue(OrganizationalUnit, items, certs, i);
00575 if(!str.isEmpty())
00576 {
00577 name = list[items[i]] + QString(" of ") + str;
00578 goto end;
00579 }
00580
00581
00582 str = uniqueSubjectValue(Email, items, certs, i);
00583 if(!str.isEmpty())
00584 {
00585 name = list[items[i]] + QString(" <") + str + '>';
00586 goto end;
00587 }
00588
00589
00590 str = uniqueSubjectValue(XMPP, items, certs, i);
00591 if(!str.isEmpty())
00592 {
00593 name = list[items[i]] + QString(" <xmpp:") + str + '>';
00594 goto end;
00595 }
00596
00597
00598 str = uniqueIssuerName(items, certs, i);
00599 if(!str.isEmpty())
00600 {
00601 name = list[items[i]] + QString(" by ") + str;
00602 goto end;
00603 }
00604
00605
00606
00607
00608 str = uniqueConstraintValue(DigitalSignature, items, certs, i);
00609 if(!str.isEmpty())
00610 {
00611 name = list[items[i]] + QString(" for ") + str;
00612 goto end;
00613 }
00614
00615
00616 str = uniqueConstraintValue(ClientAuth, items, certs, i);
00617 if(!str.isEmpty())
00618 {
00619 name = list[items[i]] + QString(" for ") + str;
00620 goto end;
00621 }
00622
00623
00624 str = uniqueConstraintValue(EmailProtection, items, certs, i);
00625 if(!str.isEmpty())
00626 {
00627 name = list[items[i]] + QString(" for ") + str;
00628 goto end;
00629 }
00630
00631
00632 str = uniqueConstraintValue(DataEncipherment, items, certs, i);
00633 if(!str.isEmpty())
00634 {
00635 name = list[items[i]] + QString(" for ") + str;
00636 goto end;
00637 }
00638
00639
00640 str = uniqueConstraintValue(EncipherOnly, items, certs, i);
00641 if(!str.isEmpty())
00642 {
00643 name = list[items[i]] + QString(" for ") + str;
00644 goto end;
00645 }
00646
00647
00648 str = uniqueConstraintValue(DecipherOnly, items, certs, i);
00649 if(!str.isEmpty())
00650 {
00651 name = list[items[i]] + QString(" for ") + str;
00652 goto end;
00653 }
00654
00655
00656 name = certs[items[i]].subjectInfoOrdered().toString();
00657
00658 end:
00659 return name;
00660 }
00661
00662 QStringList makeFriendlyNames(const QList<Certificate> &list)
00663 {
00664 QStringList names;
00665
00666
00667 foreach(const Certificate &cert, list)
00668 names += baseCertName(cert.subjectInfo());
00669
00670
00671 QList< QList<int> > itemCollisions;
00672 foreach(const QString &name, names)
00673 {
00674
00675 QList<int> items = findSameName(name, names);
00676 if(items.count() > 1)
00677 {
00678
00679 bool haveAlready = false;
00680 foreach(const QList<int> &other, itemCollisions)
00681 {
00682 foreach(int n, items)
00683 {
00684 if(other.contains(n))
00685 {
00686 haveAlready = true;
00687 break;
00688 }
00689 }
00690
00691 if(haveAlready)
00692 break;
00693 }
00694
00695 if(haveAlready)
00696 continue;
00697
00698 itemCollisions += items;
00699 }
00700 }
00701
00702
00703 foreach(const QList<int> &items, itemCollisions)
00704 {
00705
00706
00707 for(int n = 0; n < items.count(); ++n)
00708 {
00709 names[items[n]] = makeUniqueName(items, names, list, n);
00710
00711 }
00712 }
00713
00714 return names;
00715 }
00716
00717
00718
00719
00720 class CertificateInfoType::Private : public QSharedData
00721 {
00722 public:
00723 CertificateInfoType::Section section;
00724 int known;
00725 QString id;
00726
00727 Private() :
00728 section(CertificateInfoType::DN),
00729 known(-1)
00730 {
00731 }
00732 };
00733
00734 CertificateInfoType::CertificateInfoType()
00735 :d(new Private)
00736 {
00737 }
00738
00739 CertificateInfoType::CertificateInfoType(CertificateInfoTypeKnown known)
00740 :d(new Private)
00741 {
00742 d->section = knownToSection(known);
00743 d->known = known;
00744 d->id = knownToId(known);
00745 }
00746
00747 CertificateInfoType::CertificateInfoType(const QString &id, Section section)
00748 :d(new Private)
00749 {
00750 d->section = section;
00751 d->known = idToKnown(id);
00752 d->id = id;
00753 }
00754
00755 CertificateInfoType::CertificateInfoType(const CertificateInfoType &from)
00756 :d(from.d)
00757 {
00758 }
00759
00760 CertificateInfoType::~CertificateInfoType()
00761 {
00762 }
00763
00764 CertificateInfoType & CertificateInfoType::operator=(const CertificateInfoType &from)
00765 {
00766 d = from.d;
00767 return *this;
00768 }
00769
00770 CertificateInfoType::Section CertificateInfoType::section() const
00771 {
00772 return d->section;
00773 }
00774
00775 CertificateInfoTypeKnown CertificateInfoType::known() const
00776 {
00777 return (CertificateInfoTypeKnown)d->known;
00778 }
00779
00780 QString CertificateInfoType::id() const
00781 {
00782 return d->id;
00783 }
00784
00785 bool CertificateInfoType::operator<(const CertificateInfoType &other) const
00786 {
00787
00788 if(d->known != -1)
00789 {
00790 if(other.d->known == -1)
00791 return true;
00792 else if(d->known < other.d->known)
00793 return true;
00794 else
00795 return false;
00796 }
00797 else
00798 {
00799 if(other.d->known != -1)
00800 return false;
00801 else if(d->id < other.d->id)
00802 return true;
00803 else
00804 return false;
00805 }
00806 }
00807
00808 bool CertificateInfoType::operator==(const CertificateInfoType &other) const
00809 {
00810
00811 if(d->known != -1 && other.d->known != -1)
00812 {
00813
00814 if(d->known != other.d->known)
00815 return false;
00816 }
00817 else
00818 {
00819
00820 if(d->id != other.d->id)
00821 return false;
00822 }
00823
00824 if(d->section != other.d->section)
00825 return false;
00826
00827 return true;
00828 }
00829
00830
00831
00832
00833 class CertificateInfoPair::Private : public QSharedData
00834 {
00835 public:
00836 CertificateInfoType type;
00837 QString value;
00838 };
00839
00840 CertificateInfoPair::CertificateInfoPair()
00841 :d(new Private)
00842 {
00843 }
00844
00845 CertificateInfoPair::CertificateInfoPair(const CertificateInfoType &type, const QString &value)
00846 :d(new Private)
00847 {
00848 d->type = type;
00849 d->value = value;
00850 }
00851
00852 CertificateInfoPair::CertificateInfoPair(const CertificateInfoPair &from)
00853 :d(from.d)
00854 {
00855 }
00856
00857 CertificateInfoPair::~CertificateInfoPair()
00858 {
00859 }
00860
00861 CertificateInfoPair & CertificateInfoPair::operator=(const CertificateInfoPair &from)
00862 {
00863 d = from.d;
00864 return *this;
00865 }
00866
00867 CertificateInfoType CertificateInfoPair::type() const
00868 {
00869 return d->type;
00870 }
00871
00872 QString CertificateInfoPair::value() const
00873 {
00874 return d->value;
00875 }
00876
00877 bool CertificateInfoPair::operator==(const CertificateInfoPair &other) const
00878 {
00879 if(d->type == other.d->type && d->value == other.d->value)
00880 return true;
00881 return false;
00882 }
00883
00884
00885
00886
00887 class ConstraintType::Private : public QSharedData
00888 {
00889 public:
00890 ConstraintType::Section section;
00891 int known;
00892 QString id;
00893
00894 Private() :
00895 section(ConstraintType::KeyUsage),
00896 known(-1)
00897 {
00898 }
00899 };
00900
00901 ConstraintType::ConstraintType()
00902 :d(new Private)
00903 {
00904 }
00905
00906 ConstraintType::ConstraintType(ConstraintTypeKnown known)
00907 :d(new Private)
00908 {
00909 d->section = constraintKnownToSection(known);
00910 d->known = known;
00911 d->id = constraintKnownToId(known);
00912 }
00913
00914 ConstraintType::ConstraintType(const QString &id, Section section)
00915 :d(new Private)
00916 {
00917 d->section = section;
00918 d->known = constraintIdToKnown(id);
00919 d->id = id;
00920 }
00921
00922 ConstraintType::ConstraintType(const ConstraintType &from)
00923 :d(from.d)
00924 {
00925 }
00926
00927 ConstraintType::~ConstraintType()
00928 {
00929 }
00930
00931 ConstraintType & ConstraintType::operator=(const ConstraintType &from)
00932 {
00933 d = from.d;
00934 return *this;
00935 }
00936
00937 ConstraintType::Section ConstraintType::section() const
00938 {
00939 return d->section;
00940 }
00941
00942 ConstraintTypeKnown ConstraintType::known() const
00943 {
00944 return (ConstraintTypeKnown)d->known;
00945 }
00946
00947 QString ConstraintType::id() const
00948 {
00949 return d->id;
00950 }
00951
00952 bool ConstraintType::operator<(const ConstraintType &other) const
00953 {
00954
00955 if(d->known != -1)
00956 {
00957 if(other.d->known == -1)
00958 return true;
00959 else if(d->known < other.d->known)
00960 return true;
00961 else
00962 return false;
00963 }
00964 else
00965 {
00966 if(other.d->known != -1)
00967 return false;
00968 else if(d->id < other.d->id)
00969 return true;
00970 else
00971 return false;
00972 }
00973 }
00974
00975 bool ConstraintType::operator==(const ConstraintType &other) const
00976 {
00977
00978 if(d->known != -1 && other.d->known != -1)
00979 {
00980
00981 if(d->known != other.d->known)
00982 return false;
00983 }
00984 else
00985 {
00986
00987 if(d->id != other.d->id)
00988 return false;
00989 }
00990
00991 if(d->section != other.d->section)
00992 return false;
00993
00994 return true;
00995 }
00996
00997
00998
00999
01000 class CertificateOptions::Private
01001 {
01002 public:
01003 CertificateRequestFormat format;
01004
01005 QString challenge;
01006 CertificateInfoOrdered info;
01007 CertificateInfo infoMap;
01008 Constraints constraints;
01009 QStringList policies;
01010 QStringList crlLocations, issuerLocations, ocspLocations;
01011 bool isCA;
01012 int pathLimit;
01013 BigInteger serial;
01014 QDateTime start, end;
01015
01016 Private() : isCA(false), pathLimit(0)
01017 {
01018 }
01019 };
01020
01021 CertificateOptions::CertificateOptions(CertificateRequestFormat f)
01022 {
01023 d = new Private;
01024 d->format = f;
01025 }
01026
01027 CertificateOptions::CertificateOptions(const CertificateOptions &from)
01028 {
01029 d = new Private(*from.d);
01030 }
01031
01032 CertificateOptions::~CertificateOptions()
01033 {
01034 delete d;
01035 }
01036
01037 CertificateOptions & CertificateOptions::operator=(const CertificateOptions &from)
01038 {
01039 *d = *from.d;
01040 return *this;
01041 }
01042
01043 CertificateRequestFormat CertificateOptions::format() const
01044 {
01045 return d->format;
01046 }
01047
01048 void CertificateOptions::setFormat(CertificateRequestFormat f)
01049 {
01050 d->format = f;
01051 }
01052
01053 bool CertificateOptions::isValid() const
01054 {
01055
01056 if(d->infoMap.value(CommonName).isEmpty() || d->infoMap.value(Country).isEmpty())
01057 return false;
01058 if(d->infoMap.value(Country).length() != 2)
01059 return false;
01060 if(d->start >= d->end)
01061 return false;
01062 return true;
01063 }
01064
01065 QString CertificateOptions::challenge() const
01066 {
01067 return d->challenge;
01068 }
01069
01070 CertificateInfo CertificateOptions::info() const
01071 {
01072 return d->infoMap;
01073 }
01074
01075 CertificateInfoOrdered CertificateOptions::infoOrdered() const
01076 {
01077 return d->info;
01078 }
01079
01080 Constraints CertificateOptions::constraints() const
01081 {
01082 return d->constraints;
01083 }
01084
01085 QStringList CertificateOptions::policies() const
01086 {
01087 return d->policies;
01088 }
01089
01090 QStringList CertificateOptions::crlLocations() const
01091 {
01092 return d->crlLocations;
01093 }
01094
01095 QStringList CertificateOptions::issuerLocations() const
01096 {
01097 return d->issuerLocations;
01098 }
01099
01100 QStringList CertificateOptions::ocspLocations() const
01101 {
01102 return d->ocspLocations;
01103 }
01104
01105 bool CertificateOptions::isCA() const
01106 {
01107 return d->isCA;
01108 }
01109
01110 int CertificateOptions::pathLimit() const
01111 {
01112 return d->pathLimit;
01113 }
01114
01115 BigInteger CertificateOptions::serialNumber() const
01116 {
01117 return d->serial;
01118 }
01119
01120 QDateTime CertificateOptions::notValidBefore() const
01121 {
01122 return d->start;
01123 }
01124
01125 QDateTime CertificateOptions::notValidAfter() const
01126 {
01127 return d->end;
01128 }
01129
01130 void CertificateOptions::setChallenge(const QString &s)
01131 {
01132 d->challenge = s;
01133 }
01134
01135 void CertificateOptions::setInfo(const CertificateInfo &info)
01136 {
01137 d->info = mapToOrdered(info);
01138 d->infoMap = info;
01139 }
01140
01141 void CertificateOptions::setInfoOrdered(const CertificateInfoOrdered &info)
01142 {
01143 d->info = info;
01144 d->infoMap = orderedToMap(info);
01145 }
01146
01147 void CertificateOptions::setConstraints(const Constraints &constraints)
01148 {
01149 d->constraints = constraints;
01150 }
01151
01152 void CertificateOptions::setPolicies(const QStringList &policies)
01153 {
01154 d->policies = policies;
01155 }
01156
01157 void CertificateOptions::setCRLLocations(const QStringList &locations)
01158 {
01159 d->crlLocations = locations;
01160 }
01161
01162 void CertificateOptions::setIssuerLocations(const QStringList &locations)
01163 {
01164 d->issuerLocations = locations;
01165 }
01166
01167 void CertificateOptions::setOCSPLocations(const QStringList &locations)
01168 {
01169 d->ocspLocations = locations;
01170 }
01171
01172 void CertificateOptions::setAsCA(int pathLimit)
01173 {
01174 d->isCA = true;
01175 d->pathLimit = pathLimit;
01176 }
01177
01178 void CertificateOptions::setAsUser()
01179 {
01180 d->isCA = false;
01181 d->pathLimit = 0;
01182 }
01183
01184 void CertificateOptions::setSerialNumber(const BigInteger &i)
01185 {
01186 d->serial = i;
01187 }
01188
01189 void CertificateOptions::setValidityPeriod(const QDateTime &start, const QDateTime &end)
01190 {
01191 d->start = start;
01192 d->end = end;
01193 }
01194
01195
01196
01197
01198
01199
01200 static QByteArray ipaddr_str2bin(const QString &str)
01201 {
01202
01203 if(str.contains(':'))
01204 {
01205 QStringList parts = str.split(':', QString::KeepEmptyParts);
01206 if(parts.count() < 3 || parts.count() > 8)
01207 return QByteArray();
01208
01209 QByteArray ipv6(16, 0);
01210 int at = 16;
01211 int fill = 9 - parts.count();
01212 for(int n = parts.count() - 1; n >= 0; --n)
01213 {
01214 if(at <= 0)
01215 return QByteArray();
01216
01217 if(parts[n].isEmpty())
01218 {
01219 if(n == parts.count() - 1)
01220 {
01221 if(!parts[n - 1].isEmpty())
01222 return QByteArray();
01223 ipv6[--at] = 0;
01224 ipv6[--at] = 0;
01225 }
01226 else if(n == 0)
01227 {
01228 if(!parts[n + 1].isEmpty())
01229 return QByteArray();
01230 ipv6[--at] = 0;
01231 ipv6[--at] = 0;
01232 }
01233 else
01234 {
01235 for(int i = 0; i < fill; ++i)
01236 {
01237 if(at <= 0)
01238 return QByteArray();
01239 ipv6[--at] = 0;
01240 ipv6[--at] = 0;
01241 }
01242 }
01243 }
01244 else
01245 {
01246 if(parts[n].indexOf('.') == -1)
01247 {
01248 bool ok;
01249 int x = parts[n].toInt(&ok, 16);
01250 if(!ok || x < 0 || x > 0xffff)
01251 return QByteArray();
01252 ipv6[--at] = x & 0xff;
01253 ipv6[--at] = (x >> 8) & 0xff;
01254 }
01255 else
01256 {
01257 if(n != parts.count() - 1)
01258 return QByteArray();
01259
01260 QByteArray buf = ipaddr_str2bin(parts[n]);
01261 if(buf.isEmpty())
01262 return QByteArray();
01263
01264 ipv6[--at] = buf[3];
01265 ipv6[--at] = buf[2];
01266 ipv6[--at] = buf[1];
01267 ipv6[--at] = buf[0];
01268 --fill;
01269 }
01270 }
01271 }
01272
01273 return ipv6;
01274 }
01275 else if(str.contains('.'))
01276 {
01277 QStringList parts = str.split('.', QString::KeepEmptyParts);
01278 if(parts.count() != 4)
01279 return QByteArray();
01280
01281 QByteArray out(4, 0);
01282 for(int n = 0; n < 4; ++n)
01283 {
01284 bool ok;
01285 int x = parts[n].toInt(&ok);
01286 if(!ok || x < 0 || x > 0xff)
01287 return QByteArray();
01288 out[n] = (unsigned char)x;
01289 }
01290 return out;
01291 }
01292 else
01293 return QByteArray();
01294 }
01295
01296
01297 static bool cert_match_domain(const QString &certname, const QString &acedomain)
01298 {
01299
01300
01301 QString name = certname.trimmed();
01302
01303
01304
01305 if(name.length() > 0 && name[name.length()-1] == '.')
01306 name.truncate(name.length()-1);
01307
01308
01309
01310 if(name.isEmpty())
01311 return false;
01312
01313
01314 name = name.toLower();
01315
01316
01317 if(QRegExp("[^a-z0-9\\.\\*\\-]").indexIn(name) >= 0)
01318 return false;
01319
01320
01321 QStringList parts_name = name.split('.', QString::KeepEmptyParts);
01322 if(parts_name.isEmpty())
01323 return false;
01324
01325
01326
01327
01328 if(parts_name[parts_name.count()-1].contains('*'))
01329 return false;
01330 if(parts_name.count() >= 2 && parts_name[parts_name.count()-2].contains('*'))
01331 return false;
01332
01333 QStringList parts_compare = acedomain.split('.', QString::KeepEmptyParts);
01334 if(parts_compare.isEmpty())
01335 return false;
01336
01337
01338 foreach(const QString &s, parts_name)
01339 {
01340 if(s.isEmpty())
01341 return false;
01342 }
01343 foreach(const QString &s, parts_compare)
01344 {
01345 if(s.isEmpty())
01346 return false;
01347 }
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360 if(parts_name.count() != parts_compare.count())
01361 return false;
01362
01363
01364 for(int n = 0; n < parts_name.count(); ++n)
01365 {
01366 const QString &p1 = parts_name[n];
01367 const QString &p2 = parts_compare[n];
01368
01369 if(!QRegExp(p1, Qt::CaseSensitive, QRegExp::Wildcard).exactMatch(p2))
01370 return false;
01371 }
01372
01373 return true;
01374 }
01375
01376
01377 static bool cert_match_ipaddress(const QString &certname, const QByteArray &ipaddress)
01378 {
01379
01380
01381 QString name = certname.trimmed();
01382
01383
01384
01385
01386 if(name.length() >= 2 && name[0] == '[' && name[name.length()-1] == ']')
01387 name = name.mid(1, name.length() - 2);
01388
01389
01390
01391 if(name.isEmpty())
01392 return false;
01393
01394
01395 QByteArray addr = ipaddr_str2bin(name);
01396 if(addr.isEmpty())
01397 return false;
01398
01399
01400 if(addr != ipaddress)
01401 return false;
01402
01403 return true;
01404 }
01405
01406 class Certificate::Private : public QSharedData
01407 {
01408 public:
01409 CertificateInfo subjectInfoMap, issuerInfoMap;
01410
01411 void update(CertContext *c)
01412 {
01413 if(c)
01414 {
01415 subjectInfoMap = orderedToMap(c->props()->subject);
01416 issuerInfoMap = orderedToMap(c->props()->issuer);
01417 }
01418 else
01419 {
01420 subjectInfoMap = CertificateInfo();
01421 issuerInfoMap = CertificateInfo();
01422 }
01423 }
01424 };
01425
01426 Certificate::Certificate()
01427 :d(new Private)
01428 {
01429 }
01430
01431 Certificate::Certificate(const QString &fileName)
01432 :d(new Private)
01433 {
01434 *this = fromPEMFile(fileName, 0, QString());
01435 }
01436
01437 Certificate::Certificate(const CertificateOptions &opts, const PrivateKey &key, const QString &provider)
01438 :d(new Private)
01439 {
01440 CertContext *c = static_cast<CertContext *>(getContext("cert", provider));
01441 if(c->createSelfSigned(opts, *(static_cast<const PKeyContext *>(key.context()))))
01442 change(c);
01443 else
01444 delete c;
01445 }
01446
01447 Certificate::Certificate(const Certificate &from)
01448 :Algorithm(from), d(from.d)
01449 {
01450 }
01451
01452 Certificate::~Certificate()
01453 {
01454 }
01455
01456 Certificate & Certificate::operator=(const Certificate &from)
01457 {
01458 Algorithm::operator=(from);
01459 d = from.d;
01460 return *this;
01461 }
01462
01463 bool Certificate::isNull() const
01464 {
01465 return (!context() ? true : false);
01466 }
01467
01468 QDateTime Certificate::notValidBefore() const
01469 {
01470 return static_cast<const CertContext *>(context())->props()->start;
01471 }
01472
01473 QDateTime Certificate::notValidAfter() const
01474 {
01475 return static_cast<const CertContext *>(context())->props()->end;
01476 }
01477
01478 CertificateInfo Certificate::subjectInfo() const
01479 {
01480 return d->subjectInfoMap;
01481 }
01482
01483 CertificateInfoOrdered Certificate::subjectInfoOrdered() const
01484 {
01485 return static_cast<const CertContext *>(context())->props()->subject;
01486 }
01487
01488 CertificateInfo Certificate::issuerInfo() const
01489 {
01490 return d->issuerInfoMap;
01491 }
01492
01493 CertificateInfoOrdered Certificate::issuerInfoOrdered() const
01494 {
01495 return static_cast<const CertContext *>(context())->props()->issuer;
01496 }
01497
01498 Constraints Certificate::constraints() const
01499 {
01500 return static_cast<const CertContext *>(context())->props()->constraints;
01501 }
01502
01503 QStringList Certificate::policies() const
01504 {
01505 return static_cast<const CertContext *>(context())->props()->policies;
01506 }
01507
01508 QStringList Certificate::crlLocations() const
01509 {
01510 return static_cast<const CertContext *>(context())->props()->crlLocations;
01511 }
01512
01513 QStringList Certificate::issuerLocations() const
01514 {
01515 return static_cast<const CertContext *>(context())->props()->issuerLocations;
01516 }
01517
01518 QStringList Certificate::ocspLocations() const
01519 {
01520 return static_cast<const CertContext *>(context())->props()->ocspLocations;
01521 }
01522
01523 QString Certificate::commonName() const
01524 {
01525 return d->subjectInfoMap.value(CommonName);
01526 }
01527
01528 BigInteger Certificate::serialNumber() const
01529 {
01530 return static_cast<const CertContext *>(context())->props()->serial;
01531 }
01532
01533 PublicKey Certificate::subjectPublicKey() const
01534 {
01535 PKeyContext *c = static_cast<const CertContext *>(context())->subjectPublicKey();
01536 PublicKey key;
01537 key.change(c);
01538 return key;
01539 }
01540
01541 bool Certificate::isCA() const
01542 {
01543 return static_cast<const CertContext *>(context())->props()->isCA;
01544 }
01545
01546 bool Certificate::isSelfSigned() const
01547 {
01548 return static_cast<const CertContext *>(context())->props()->isSelfSigned;
01549 }
01550
01551 bool Certificate::isIssuerOf(const Certificate &other) const
01552 {
01553 const CertContext *cc = static_cast<const CertContext *>(other.context());
01554 return static_cast<const CertContext *>(context())->isIssuerOf(cc);
01555 }
01556
01557 int Certificate::pathLimit() const
01558 {
01559 return static_cast<const CertContext *>(context())->props()->pathLimit;
01560 }
01561
01562 SignatureAlgorithm Certificate::signatureAlgorithm() const
01563 {
01564 return static_cast<const CertContext *>(context())->props()->sigalgo;
01565 }
01566
01567 QByteArray Certificate::subjectKeyId() const
01568 {
01569 return static_cast<const CertContext *>(context())->props()->subjectId;
01570 }
01571
01572 QByteArray Certificate::issuerKeyId() const
01573 {
01574 return static_cast<const CertContext *>(context())->props()->issuerId;
01575 }
01576
01577 Validity Certificate::validate(const CertificateCollection &trusted, const CertificateCollection &untrusted, UsageMode u, ValidateFlags vf) const
01578 {
01579 QList<Certificate> issuers = trusted.certificates() + untrusted.certificates();
01580 CertificateChain chain;
01581 chain += *this;
01582 Validity result;
01583 chain = chain.complete(issuers, &result);
01584 if(result != ValidityGood)
01585 return result;
01586 return chain.validate(trusted, untrusted.crls(), u, vf);
01587 }
01588
01589 QByteArray Certificate::toDER() const
01590 {
01591 return static_cast<const CertContext *>(context())->toDER();
01592 }
01593
01594 QString Certificate::toPEM() const
01595 {
01596 return static_cast<const CertContext *>(context())->toPEM();
01597 }
01598
01599 bool Certificate::toPEMFile(const QString &fileName) const
01600 {
01601 return stringToFile(fileName, toPEM());
01602 }
01603
01604 Certificate Certificate::fromDER(const QByteArray &a, ConvertResult *result, const QString &provider)
01605 {
01606 Certificate c;
01607 CertContext *cc = static_cast<CertContext *>(getContext("cert", provider));
01608 ConvertResult r = cc->fromDER(a);
01609 if(result)
01610 *result = r;
01611 if(r == ConvertGood)
01612 c.change(cc);
01613 else
01614 delete cc;
01615 return c;
01616 }
01617
01618 Certificate Certificate::fromPEM(const QString &s, ConvertResult *result, const QString &provider)
01619 {
01620 Certificate c;
01621 CertContext *cc = static_cast<CertContext *>(getContext("cert", provider));
01622 ConvertResult r = cc->fromPEM(s);
01623 if(result)
01624 *result = r;
01625 if(r == ConvertGood)
01626 c.change(cc);
01627 else
01628 delete cc;
01629 return c;
01630 }
01631
01632 Certificate Certificate::fromPEMFile(const QString &fileName, ConvertResult *result, const QString &provider)
01633 {
01634 QString pem;
01635 if(!stringFromFile(fileName, &pem))
01636 {
01637 if(result)
01638 *result = ErrorFile;
01639 return Certificate();
01640 }
01641 return fromPEM(pem, result, provider);
01642 }
01643
01644
01645
01646 bool Certificate::matchesHostName(const QString &host) const
01647 {
01648 QByteArray ipaddr = ipaddr_str2bin(host);
01649 if(!ipaddr.isEmpty())
01650 {
01651
01652 foreach(const QString &s, subjectInfo().values(IPAddress))
01653 {
01654 if(cert_match_ipaddress(s, ipaddr))
01655 return true;
01656 }
01657
01658
01659 foreach(const QString &s, subjectInfo().values(DNS))
01660 {
01661 if(cert_match_ipaddress(s, ipaddr))
01662 return true;
01663 }
01664
01665
01666 foreach(const QString &s, subjectInfo().values(CommonName))
01667 {
01668 if(cert_match_ipaddress(s, ipaddr))
01669 return true;
01670 }
01671 }
01672 else
01673 {
01674
01675 QString name = host.toLower();
01676
01677
01678 name = QString::fromLatin1(QUrl::toAce(name));
01679
01680
01681 if(name.contains('*'))
01682 return false;
01683
01684
01685 if(name.length() > 0 && name[name.length()-1] == '.')
01686 name.truncate(name.length()-1);
01687
01688
01689 if(name.isEmpty())
01690 return false;
01691
01692
01693 foreach(const QString &s, subjectInfo().values(DNS))
01694 {
01695 if(cert_match_domain(s, name))
01696 return true;
01697 }
01698
01699
01700 foreach(const QString &s, subjectInfo().values(CommonName))
01701 {
01702 if(cert_match_domain(s, name))
01703 return true;
01704 }
01705 }
01706
01707 return false;
01708 }
01709
01710 bool Certificate::operator==(const Certificate &otherCert) const
01711 {
01712 if(isNull())
01713 {
01714 if(otherCert.isNull())
01715 return true;
01716 else
01717 return false;
01718 }
01719 else if(otherCert.isNull())
01720 return false;
01721
01722 const CertContext *other = static_cast<const CertContext *>(otherCert.context());
01723 return static_cast<const CertContext *>(context())->compare(other);
01724 }
01725
01726 void Certificate::change(CertContext *c)
01727 {
01728 Algorithm::change(c);
01729 d->update(static_cast<CertContext *>(context()));
01730 }
01731
01732 Validity Certificate::chain_validate(const CertificateChain &chain, const CertificateCollection &trusted, const QList<CRL> &untrusted_crls, UsageMode u, ValidateFlags vf) const
01733 {
01734 QList<CertContext*> chain_list;
01735 QList<CertContext*> trusted_list;
01736 QList<CRLContext*> crl_list;
01737
01738 QList<Certificate> chain_certs = chain;
01739 QList<Certificate> trusted_certs = trusted.certificates();
01740 QList<CRL> crls = trusted.crls() + untrusted_crls;
01741
01742 for(int n = 0; n < chain_certs.count(); ++n)
01743 {
01744 CertContext *c = static_cast<CertContext *>(chain_certs[n].context());
01745 chain_list += c;
01746 }
01747 for(int n = 0; n < trusted_certs.count(); ++n)
01748 {
01749 CertContext *c = static_cast<CertContext *>(trusted_certs[n].context());
01750 trusted_list += c;
01751 }
01752 for(int n = 0; n < crls.count(); ++n)
01753 {
01754 CRLContext *c = static_cast<CRLContext *>(crls[n].context());
01755 crl_list += c;
01756 }
01757
01758 return static_cast<const CertContext *>(context())->validate_chain(chain_list, trusted_list, crl_list, u, vf);
01759 }
01760
01761 CertificateChain Certificate::chain_complete(const CertificateChain &chain, const QList<Certificate> &issuers, Validity *result) const
01762 {
01763 CertificateChain out;
01764 QList<Certificate> pool = issuers + chain.mid(1);
01765 out += chain.first();
01766 if(result)
01767 *result = ValidityGood;
01768 while(!out.last().isSelfSigned())
01769 {
01770
01771 int at = -1;
01772 for(int n = 0; n < pool.count(); ++n)
01773 {
01774
01775 if(pool[n].isIssuerOf(out.last()))
01776 {
01777
01778 at = n;
01779 break;
01780 }
01781
01782 }
01783 if(at == -1)
01784 {
01785 if(result)
01786 *result = ErrorInvalidCA;
01787 break;
01788 }
01789
01790
01791 Certificate next = pool.takeAt(at);
01792
01793
01794 if(out.contains(next))
01795 break;
01796
01797
01798 out += next;
01799 }
01800 return out;
01801 }
01802
01803
01804
01805
01806 class CertificateRequest::Private : public QSharedData
01807 {
01808 public:
01809 CertificateInfo subjectInfoMap;
01810
01811 void update(CSRContext *c)
01812 {
01813 if(c)
01814 subjectInfoMap = orderedToMap(c->props()->subject);
01815 else
01816 subjectInfoMap = CertificateInfo();
01817 }
01818 };
01819
01820 CertificateRequest::CertificateRequest()
01821 :d(new Private)
01822 {
01823 }
01824
01825 CertificateRequest::CertificateRequest(const QString &fileName)
01826 :d(new Private)
01827 {
01828 *this = fromPEMFile(fileName, 0, QString());
01829 }
01830
01831 CertificateRequest::CertificateRequest(const CertificateOptions &opts, const PrivateKey &key, const QString &provider)
01832 :d(new Private)
01833 {
01834 CSRContext *c = static_cast<CSRContext *>(getContext("csr", provider));
01835 if(c->createRequest(opts, *(static_cast<const PKeyContext *>(key.context()))))
01836 change(c);
01837 else
01838 delete c;
01839 }
01840
01841 CertificateRequest::CertificateRequest(const CertificateRequest &from)
01842 :Algorithm(from), d(from.d)
01843 {
01844 }
01845
01846 CertificateRequest::~CertificateRequest()
01847 {
01848 }
01849
01850 CertificateRequest & CertificateRequest::operator=(const CertificateRequest &from)
01851 {
01852 Algorithm::operator=(from);
01853 d = from.d;
01854 return *this;
01855 }
01856
01857 bool CertificateRequest::isNull() const
01858 {
01859 return (!context() ? true : false);
01860 }
01861
01862 bool CertificateRequest::canUseFormat(CertificateRequestFormat f, const QString &provider)
01863 {
01864 CSRContext *c = static_cast<CSRContext *>(getContext("csr", provider));
01865 bool ok = c->canUseFormat(f);
01866 delete c;
01867 return ok;
01868 }
01869
01870 CertificateRequestFormat CertificateRequest::format() const
01871 {
01872 if(isNull())
01873 return PKCS10;
01874 return static_cast<const CSRContext *>(context())->props()->format;
01875 }
01876
01877 CertificateInfo CertificateRequest::subjectInfo() const
01878 {
01879 return d->subjectInfoMap;
01880 }
01881
01882 CertificateInfoOrdered CertificateRequest::subjectInfoOrdered() const
01883 {
01884 return static_cast<const CSRContext *>(context())->props()->subject;
01885 }
01886
01887 Constraints CertificateRequest::constraints() const
01888 {
01889 return static_cast<const CSRContext *>(context())->props()->constraints;
01890 }
01891
01892 QStringList CertificateRequest::policies() const
01893 {
01894 return static_cast<const CSRContext *>(context())->props()->policies;
01895 }
01896
01897 PublicKey CertificateRequest::subjectPublicKey() const
01898 {
01899 PKeyContext *c = static_cast<const CSRContext *>(context())->subjectPublicKey();
01900 PublicKey key;
01901 key.change(c);
01902 return key;
01903 }
01904
01905 bool CertificateRequest::isCA() const
01906 {
01907 return static_cast<const CSRContext *>(context())->props()->isCA;
01908 }
01909
01910 int CertificateRequest::pathLimit() const
01911 {
01912 return static_cast<const CSRContext *>(context())->props()->pathLimit;
01913 }
01914
01915 QString CertificateRequest::challenge() const
01916 {
01917 return static_cast<const CSRContext *>(context())->props()->challenge;
01918 }
01919
01920 SignatureAlgorithm CertificateRequest::signatureAlgorithm() const
01921 {
01922 return static_cast<const CSRContext *>(context())->props()->sigalgo;
01923 }
01924
01925 bool CertificateRequest::operator==(const CertificateRequest &otherCsr) const
01926 {
01927 if(isNull())
01928 {
01929 if(otherCsr.isNull())
01930 return true;
01931 else
01932 return false;
01933 }
01934 else if(otherCsr.isNull())
01935 return false;
01936
01937 const CSRContext *other = static_cast<const CSRContext *>(otherCsr.context());
01938 return static_cast<const CSRContext *>(context())->compare(other);
01939 }
01940
01941 QByteArray CertificateRequest::toDER() const
01942 {
01943 return static_cast<const CSRContext *>(context())->toDER();
01944 }
01945
01946 QString CertificateRequest::toPEM() const
01947 {
01948 return static_cast<const CSRContext *>(context())->toPEM();
01949 }
01950
01951 bool CertificateRequest::toPEMFile(const QString &fileName) const
01952 {
01953 return stringToFile(fileName, toPEM());
01954 }
01955
01956 CertificateRequest CertificateRequest::fromDER(const QByteArray &a, ConvertResult *result, const QString &provider)
01957 {
01958 CertificateRequest c;
01959 CSRContext *csr = static_cast<CSRContext *>(getContext("csr", provider));
01960 ConvertResult r = csr->fromDER(a);
01961 if(result)
01962 *result = r;
01963 if(r == ConvertGood)
01964 c.change(csr);
01965 else
01966 delete csr;
01967 return c;
01968 }
01969
01970 CertificateRequest CertificateRequest::fromPEM(const QString &s, ConvertResult *result, const QString &provider)
01971 {
01972 CertificateRequest c;
01973 CSRContext *csr = static_cast<CSRContext *>(getContext("csr", provider));
01974 ConvertResult r = csr->fromPEM(s);
01975 if(result)
01976 *result = r;
01977 if(r == ConvertGood)
01978 c.change(csr);
01979 else
01980 delete csr;
01981 return c;
01982 }
01983
01984 CertificateRequest CertificateRequest::fromPEMFile(const QString &fileName, ConvertResult *result, const QString &provider)
01985 {
01986 QString pem;
01987 if(!stringFromFile(fileName, &pem))
01988 {
01989 if(result)
01990 *result = ErrorFile;
01991 return CertificateRequest();
01992 }
01993 return fromPEM(pem, result, provider);
01994 }
01995
01996 QString CertificateRequest::toString() const
01997 {
01998 return static_cast<const CSRContext *>(context())->toSPKAC();
01999 }
02000
02001 CertificateRequest CertificateRequest::fromString(const QString &s, ConvertResult *result, const QString &provider)
02002 {
02003 CertificateRequest c;
02004 CSRContext *csr = static_cast<CSRContext *>(getContext("csr", provider));
02005 ConvertResult r = csr->fromSPKAC(s);
02006 if(result)
02007 *result = r;
02008 if(r == ConvertGood)
02009 c.change(csr);
02010 else
02011 delete csr;
02012 return c;
02013 }
02014
02015 void CertificateRequest::change(CSRContext *c)
02016 {
02017 Algorithm::change(c);
02018 d->update(static_cast<CSRContext *>(context()));
02019 }
02020
02021
02022
02023
02024 CRLEntry::CRLEntry()
02025 {
02026 _reason = Unspecified;
02027 }
02028
02029 CRLEntry::CRLEntry(const Certificate &c, Reason r)
02030 {
02031 _serial = c.serialNumber();
02032 _time = QDateTime::currentDateTime();
02033 _reason = r;
02034 }
02035
02036 CRLEntry::CRLEntry(const BigInteger serial, const QDateTime &time, Reason r)
02037 {
02038 _serial = serial;
02039 _time = time;
02040 _reason = r;
02041 }
02042
02043 CRLEntry::CRLEntry(const CRLEntry &from)
02044 :_serial(from._serial), _time(from._time), _reason(from._reason)
02045 {
02046 }
02047
02048 CRLEntry::~CRLEntry()
02049 {
02050 }
02051
02052 CRLEntry & CRLEntry::operator=(const CRLEntry &from)
02053 {
02054 _serial = from._serial;
02055 _time = from._time;
02056 _reason = from._reason;
02057 return *this;
02058 }
02059
02060 bool CRLEntry::isNull() const
02061 {
02062 return (_time.isNull());
02063 }
02064
02065 BigInteger CRLEntry::serialNumber() const
02066 {
02067 return _serial;
02068 }
02069
02070 QDateTime CRLEntry::time() const
02071 {
02072 return _time;
02073 }
02074
02075 CRLEntry::Reason CRLEntry::reason() const
02076 {
02077 return _reason;
02078 }
02079
02080 bool CRLEntry::operator==(const CRLEntry &otherEntry) const
02081 {
02082 if(isNull())
02083 {
02084 if(otherEntry.isNull())
02085 return true;
02086 else
02087 return false;
02088 }
02089 else if(otherEntry.isNull())
02090 return false;
02091
02092 if((_serial != otherEntry._serial) ||
02093 (_time != otherEntry._time) ||
02094 (_reason != otherEntry._reason))
02095 {
02096 return false;
02097 }
02098 return true;
02099 }
02100
02101 bool CRLEntry::operator<(const CRLEntry &otherEntry) const
02102 {
02103 if(isNull() || otherEntry.isNull())
02104 return false;
02105
02106 if(_serial < otherEntry._serial)
02107 return true;
02108
02109 return false;
02110 }
02111
02112
02113
02114
02115 class CRL::Private : public QSharedData
02116 {
02117 public:
02118 CertificateInfo issuerInfoMap;
02119
02120 void update(CRLContext *c)
02121 {
02122 if(c)
02123 issuerInfoMap = orderedToMap(c->props()->issuer);
02124 else
02125 issuerInfoMap = CertificateInfo();
02126 }
02127 };
02128
02129 CRL::CRL()
02130 :d(new Private)
02131 {
02132 }
02133
02134 CRL::CRL(const CRL &from)
02135 :Algorithm(from), d(from.d)
02136 {
02137 }
02138
02139 CRL::~CRL()
02140 {
02141 }
02142
02143 CRL & CRL::operator=(const CRL &from)
02144 {
02145 Algorithm::operator=(from);
02146 d = from.d;
02147 return *this;
02148 }
02149
02150 bool CRL::isNull() const
02151 {
02152 return (!context() ? true : false);
02153 }
02154
02155 CertificateInfo CRL::issuerInfo() const
02156 {
02157 return d->issuerInfoMap;
02158 }
02159
02160 CertificateInfoOrdered CRL::issuerInfoOrdered() const
02161 {
02162 return static_cast<const CRLContext *>(context())->props()->issuer;
02163 }
02164
02165 int CRL::number() const
02166 {
02167 return static_cast<const CRLContext *>(context())->props()->number;
02168 }
02169
02170 QDateTime CRL::thisUpdate() const
02171 {
02172 return static_cast<const CRLContext *>(context())->props()->thisUpdate;
02173 }
02174
02175 QDateTime CRL::nextUpdate() const
02176 {
02177 return static_cast<const CRLContext *>(context())->props()->nextUpdate;
02178 }
02179
02180 QList<CRLEntry> CRL::revoked() const
02181 {
02182 return static_cast<const CRLContext *>(context())->props()->revoked;
02183 }
02184
02185 SignatureAlgorithm CRL::signatureAlgorithm() const
02186 {
02187 return static_cast<const CRLContext *>(context())->props()->sigalgo;
02188 }
02189
02190 QByteArray CRL::issuerKeyId() const
02191 {
02192 return static_cast<const CRLContext *>(context())->props()->issuerId;
02193 }
02194
02195 QByteArray CRL::toDER() const
02196 {
02197 return static_cast<const CRLContext *>(context())->toDER();
02198 }
02199
02200 QString CRL::toPEM() const
02201 {
02202 return static_cast<const CRLContext *>(context())->toPEM();
02203 }
02204
02205 bool CRL::operator==(const CRL &otherCrl) const
02206 {
02207 if(isNull())
02208 {
02209 if(otherCrl.isNull())
02210 return true;
02211 else
02212 return false;
02213 }
02214 else if(otherCrl.isNull())
02215 return false;
02216
02217 const CRLContext *other = static_cast<const CRLContext *>(otherCrl.context());
02218 return static_cast<const CRLContext *>(context())->compare(other);
02219 }
02220
02221 CRL CRL::fromDER(const QByteArray &a, ConvertResult *result, const QString &provider)
02222 {
02223 CRL c;
02224 CRLContext *cc = static_cast<CRLContext *>(getContext("crl", provider));
02225 ConvertResult r = cc->fromDER(a);
02226 if(result)
02227 *result = r;
02228 if(r == ConvertGood)
02229 c.change(cc);
02230 else
02231 delete cc;
02232 return c;
02233 }
02234
02235 CRL CRL::fromPEM(const QString &s, ConvertResult *result, const QString &provider)
02236 {
02237 CRL c;
02238 CRLContext *cc = static_cast<CRLContext *>(getContext("crl", provider));
02239 ConvertResult r = cc->fromPEM(s);
02240 if(result)
02241 *result = r;
02242 if(r == ConvertGood)
02243 c.change(cc);
02244 else
02245 delete cc;
02246 return c;
02247 }
02248
02249 CRL CRL::fromPEMFile(const QString &fileName, ConvertResult *result, const QString &provider)
02250 {
02251 QString pem;
02252 if(!stringFromFile(fileName, &pem))
02253 {
02254 if(result)
02255 *result = ErrorFile;
02256 return CRL();
02257 }
02258 return fromPEM(pem, result, provider);
02259 }
02260
02261 bool CRL::toPEMFile(const QString &fileName) const
02262 {
02263 return stringToFile(fileName, toPEM());
02264 }
02265
02266 void CRL::change(CRLContext *c)
02267 {
02268 Algorithm::change(c);
02269 d->update(static_cast<CRLContext *>(context()));
02270 }
02271
02272
02273
02274
02275
02276
02277 static QString readNextPem(QTextStream *ts, bool *isCRL)
02278 {
02279 QString pem;
02280 bool crl = false;
02281 bool found = false;
02282 bool done = false;
02283 while(!ts->atEnd())
02284 {
02285 QString line = ts->readLine();
02286 if(!found)
02287 {
02288 if(line.startsWith("-----BEGIN "))
02289 {
02290 if(line.contains("CERTIFICATE"))
02291 {
02292 found = true;
02293 pem += line + '\n';
02294 crl = false;
02295 }
02296 else if(line.contains("CRL"))
02297 {
02298 found = true;
02299 pem += line + '\n';
02300 crl = true;
02301 }
02302 }
02303 }
02304 else
02305 {
02306 pem += line + '\n';
02307 if(line.startsWith("-----END "))
02308 {
02309 done = true;
02310 break;
02311 }
02312 }
02313 }
02314 if(!done)
02315 return QString();
02316 if(isCRL)
02317 *isCRL = crl;
02318 return pem;
02319 }
02320
02321 class CertificateCollection::Private : public QSharedData
02322 {
02323 public:
02324 QList<Certificate> certs;
02325 QList<CRL> crls;
02326 };
02327
02328 CertificateCollection::CertificateCollection()
02329 :d(new Private)
02330 {
02331 }
02332
02333 CertificateCollection::CertificateCollection(const CertificateCollection &from)
02334 :d(from.d)
02335 {
02336 }
02337
02338 CertificateCollection::~CertificateCollection()
02339 {
02340 }
02341
02342 CertificateCollection & CertificateCollection::operator=(const CertificateCollection &from)
02343 {
02344 d = from.d;
02345 return *this;
02346 }
02347
02348 void CertificateCollection::addCertificate(const Certificate &cert)
02349 {
02350 d->certs.append(cert);
02351 }
02352
02353 void CertificateCollection::addCRL(const CRL &crl)
02354 {
02355 d->crls.append(crl);
02356 }
02357
02358 QList<Certificate> CertificateCollection::certificates() const
02359 {
02360 return d->certs;
02361 }
02362
02363 QList<CRL> CertificateCollection::crls() const
02364 {
02365 return d->crls;
02366 }
02367
02368 void CertificateCollection::append(const CertificateCollection &other)
02369 {
02370 d->certs += other.d->certs;
02371 d->crls += other.d->crls;
02372 }
02373
02374 CertificateCollection CertificateCollection::operator+(const CertificateCollection &other) const
02375 {
02376 CertificateCollection c = *this;
02377 c.append(other);
02378 return c;
02379 }
02380
02381 CertificateCollection & CertificateCollection::operator+=(const CertificateCollection &other)
02382 {
02383 append(other);
02384 return *this;
02385 }
02386
02387 bool CertificateCollection::canUsePKCS7(const QString &provider)
02388 {
02389 return isSupported("certcollection", provider);
02390 }
02391
02392 bool CertificateCollection::toFlatTextFile(const QString &fileName)
02393 {
02394 QFile f(fileName);
02395 if(!f.open(QFile::WriteOnly))
02396 return false;
02397
02398 QTextStream ts(&f);
02399 int n;
02400 for(n = 0; n < d->certs.count(); ++n)
02401 ts << d->certs[n].toPEM();
02402 for(n = 0; n < d->crls.count(); ++n)
02403 ts << d->crls[n].toPEM();
02404 return true;
02405 }
02406
02407 bool CertificateCollection::toPKCS7File(const QString &fileName, const QString &provider)
02408 {
02409 CertCollectionContext *col = static_cast<CertCollectionContext *>(getContext("certcollection", provider));
02410
02411 QList<CertContext*> cert_list;
02412 QList<CRLContext*> crl_list;
02413 int n;
02414 for(n = 0; n < d->certs.count(); ++n)
02415 {
02416 CertContext *c = static_cast<CertContext *>(d->certs[n].context());
02417 cert_list += c;
02418 }
02419 for(n = 0; n < d->crls.count(); ++n)
02420 {
02421 CRLContext *c = static_cast<CRLContext *>(d->crls[n].context());
02422 crl_list += c;
02423 }
02424
02425 QByteArray result = col->toPKCS7(cert_list, crl_list);
02426 delete col;
02427
02428 return arrayToFile(fileName, result);
02429 }
02430
02431 CertificateCollection CertificateCollection::fromFlatTextFile(const QString &fileName, ConvertResult *result, const QString &provider)
02432 {
02433 QFile f(fileName);
02434 if(!f.open(QFile::ReadOnly))
02435 {
02436 if(result)
02437 *result = ErrorFile;
02438 return CertificateCollection();
02439 }
02440
02441 CertificateCollection certs;
02442 QTextStream ts(&f);
02443 while(1)
02444 {
02445 bool isCRL = false;
02446 QString pem = readNextPem(&ts, &isCRL);
02447 if(pem.isNull())
02448 break;
02449 if(isCRL)
02450 {
02451 CRL c = CRL::fromPEM(pem, 0, provider);
02452 if(!c.isNull())
02453 certs.addCRL(c);
02454 }
02455 else
02456 {
02457 Certificate c = Certificate::fromPEM(pem, 0, provider);
02458 if(!c.isNull())
02459 certs.addCertificate(c);
02460 }
02461 }
02462
02463 if(result)
02464 *result = ConvertGood;
02465
02466 return certs;
02467 }
02468
02469 CertificateCollection CertificateCollection::fromPKCS7File(const QString &fileName, ConvertResult *result, const QString &provider)
02470 {
02471 QByteArray der;
02472 if(!arrayFromFile(fileName, &der))
02473 {
02474 if(result)
02475 *result = ErrorFile;
02476 return CertificateCollection();
02477 }
02478
02479 CertificateCollection certs;
02480
02481 QList<CertContext*> cert_list;
02482 QList<CRLContext*> crl_list;
02483 CertCollectionContext *col = static_cast<CertCollectionContext *>(getContext("certcollection", provider));
02484 ConvertResult r = col->fromPKCS7(der, &cert_list, &crl_list);
02485 delete col;
02486
02487 if(result)
02488 *result = r;
02489 if(r == ConvertGood)
02490 {
02491 int n;
02492 for(n = 0; n < cert_list.count(); ++n)
02493 {
02494 Certificate c;
02495 c.change(cert_list[n]);
02496 certs.addCertificate(c);
02497 }
02498 for(n = 0; n < crl_list.count(); ++n)
02499 {
02500 CRL c;
02501 c.change(crl_list[n]);
02502 certs.addCRL(c);
02503 }
02504 }
02505 return certs;
02506 }
02507
02508
02509
02510
02511 CertificateAuthority::CertificateAuthority(const Certificate &cert, const PrivateKey &key, const QString &provider)
02512 :Algorithm("ca", provider)
02513 {
02514 static_cast<CAContext *>(context())->setup(*(static_cast<const CertContext *>(cert.context())), *(static_cast<const PKeyContext *>(key.context())));
02515 }
02516
02517 CertificateAuthority::CertificateAuthority(const CertificateAuthority &from)
02518 :Algorithm(from)
02519 {
02520 }
02521
02522 CertificateAuthority::~CertificateAuthority()
02523 {
02524 }
02525
02526 CertificateAuthority & CertificateAuthority::operator=(const CertificateAuthority &from)
02527 {
02528 Algorithm::operator=(from);
02529 return *this;
02530 }
02531
02532 Certificate CertificateAuthority::certificate() const
02533 {
02534 Certificate c;
02535 c.change(static_cast<const CAContext *>(context())->certificate());
02536 return c;
02537 }
02538
02539 Certificate CertificateAuthority::signRequest(const CertificateRequest &req, const QDateTime ¬ValidAfter) const
02540 {
02541 Certificate c;
02542 CertContext *cc = static_cast<const CAContext *>(context())->signRequest(*(static_cast<const CSRContext *>(req.context())), notValidAfter);
02543 if(cc)
02544 c.change(cc);
02545 return c;
02546 }
02547
02548 CRL CertificateAuthority::createCRL(const QDateTime &nextUpdate) const
02549 {
02550 CRL crl;
02551 CRLContext *cc = static_cast<const CAContext *>(context())->createCRL(nextUpdate);
02552 if(cc)
02553 crl.change(cc);
02554 return crl;
02555 }
02556
02557 CRL CertificateAuthority::updateCRL(const CRL &crl, const QList<CRLEntry> &entries, const QDateTime &nextUpdate) const
02558 {
02559 CRL new_crl;
02560 CRLContext *cc = static_cast<const CAContext *>(context())->updateCRL(*(static_cast<const CRLContext *>(crl.context())), entries, nextUpdate);
02561 if(cc)
02562 new_crl.change(cc);
02563 return new_crl;
02564 }
02565
02566
02567
02568
02569 class KeyBundle::Private : public QSharedData
02570 {
02571 public:
02572 QString name;
02573 CertificateChain chain;
02574 PrivateKey key;
02575 };
02576
02577 KeyBundle::KeyBundle()
02578 :d(new Private)
02579 {
02580 }
02581
02582 KeyBundle::KeyBundle(const QString &fileName, const SecureArray &passphrase)
02583 :d(new Private)
02584 {
02585 *this = fromFile(fileName, passphrase, 0, QString());
02586 }
02587
02588 KeyBundle::KeyBundle(const KeyBundle &from)
02589 :d(from.d)
02590 {
02591 }
02592
02593 KeyBundle::~KeyBundle()
02594 {
02595 }
02596
02597 KeyBundle & KeyBundle::operator=(const KeyBundle &from)
02598 {
02599 d = from.d;
02600 return *this;
02601 }
02602
02603 bool KeyBundle::isNull() const
02604 {
02605 return d->chain.isEmpty();
02606 }
02607
02608 QString KeyBundle::name() const
02609 {
02610 return d->name;
02611 }
02612
02613 CertificateChain KeyBundle::certificateChain() const
02614 {
02615 return d->chain;
02616 }
02617
02618 PrivateKey KeyBundle::privateKey() const
02619 {
02620 return d->key;
02621 }
02622
02623 void KeyBundle::setName(const QString &s)
02624 {
02625 d->name = s;
02626 }
02627
02628 void KeyBundle::setCertificateChainAndKey(const CertificateChain &c, const PrivateKey &key)
02629 {
02630 d->chain = c;
02631 d->key = key;
02632 }
02633
02634 QByteArray KeyBundle::toArray(const SecureArray &passphrase, const QString &provider) const
02635 {
02636 PKCS12Context *pix = static_cast<PKCS12Context *>(getContext("pkcs12", provider));
02637
02638 QList<const CertContext*> list;
02639 for(int n = 0; n < d->chain.count(); ++n)
02640 list.append(static_cast<const CertContext *>(d->chain[n].context()));
02641 QByteArray buf = pix->toPKCS12(d->name, list, *(static_cast<const PKeyContext *>(d->key.context())), passphrase);
02642 delete pix;
02643
02644 return buf;
02645 }
02646
02647 bool KeyBundle::toFile(const QString &fileName, const SecureArray &passphrase, const QString &provider) const
02648 {
02649 return arrayToFile(fileName, toArray(passphrase, provider));
02650 }
02651
02652 KeyBundle KeyBundle::fromArray(const QByteArray &a, const SecureArray &passphrase, ConvertResult *result, const QString &provider)
02653 {
02654 KeyBundle bundle;
02655 get_pkcs12_der(a, QString(), (void *)&a, passphrase, result, provider, &bundle.d->name, &bundle.d->chain, &bundle.d->key);
02656 return bundle;
02657 }
02658
02659 KeyBundle KeyBundle::fromFile(const QString &fileName, const SecureArray &passphrase, ConvertResult *result, const QString &provider)
02660 {
02661 QByteArray der;
02662 if(!arrayFromFile(fileName, &der))
02663 {
02664 if(result)
02665 *result = ErrorFile;
02666 return KeyBundle();
02667 }
02668
02669 KeyBundle bundle;
02670 get_pkcs12_der(der, fileName, 0, passphrase, result, provider, &bundle.d->name, &bundle.d->chain, &bundle.d->key);
02671 return bundle;
02672 }
02673
02674
02675
02676
02677 PGPKey::PGPKey()
02678 {
02679 }
02680
02681 PGPKey::PGPKey(const QString &fileName)
02682 {
02683 *this = fromFile(fileName, 0, QString());
02684 }
02685
02686 PGPKey::PGPKey(const PGPKey &from)
02687 :Algorithm(from)
02688 {
02689 }
02690
02691 PGPKey::~PGPKey()
02692 {
02693 }
02694
02695 PGPKey & PGPKey::operator=(const PGPKey &from)
02696 {
02697 Algorithm::operator=(from);
02698 return *this;
02699 }
02700
02701 bool PGPKey::isNull() const
02702 {
02703 return (!context() ? true : false);
02704 }
02705
02706 QString PGPKey::keyId() const
02707 {
02708 return static_cast<const PGPKeyContext *>(context())->props()->keyId;
02709 }
02710
02711 QString PGPKey::primaryUserId() const
02712 {
02713 return static_cast<const PGPKeyContext *>(context())->props()->userIds.first();
02714 }
02715
02716 QStringList PGPKey::userIds() const
02717 {
02718 return static_cast<const PGPKeyContext *>(context())->props()->userIds;
02719 }
02720
02721 bool PGPKey::isSecret() const
02722 {
02723 return static_cast<const PGPKeyContext *>(context())->props()->isSecret;
02724 }
02725
02726 QDateTime PGPKey::creationDate() const
02727 {
02728 return static_cast<const PGPKeyContext *>(context())->props()->creationDate;
02729 }
02730
02731 QDateTime PGPKey::expirationDate() const
02732 {
02733 return static_cast<const PGPKeyContext *>(context())->props()->expirationDate;
02734 }
02735
02736 QString PGPKey::fingerprint() const
02737 {
02738 return static_cast<const PGPKeyContext *>(context())->props()->fingerprint;
02739 }
02740
02741 bool PGPKey::inKeyring() const
02742 {
02743 return static_cast<const PGPKeyContext *>(context())->props()->inKeyring;
02744 }
02745
02746 bool PGPKey::isTrusted() const
02747 {
02748 return static_cast<const PGPKeyContext *>(context())->props()->isTrusted;
02749 }
02750
02751 QByteArray PGPKey::toArray() const
02752 {
02753 return static_cast<const PGPKeyContext *>(context())->toBinary();
02754 }
02755
02756 QString PGPKey::toString() const
02757 {
02758 return static_cast<const PGPKeyContext *>(context())->toAscii();
02759 }
02760
02761 bool PGPKey::toFile(const QString &fileName) const
02762 {
02763 return stringToFile(fileName, toString());
02764 }
02765
02766 PGPKey PGPKey::fromArray(const QByteArray &a, ConvertResult *result, const QString &provider)
02767 {
02768 PGPKey k;
02769 PGPKeyContext *kc = static_cast<PGPKeyContext *>(getContext("pgpkey", provider));
02770 ConvertResult r = kc->fromBinary(a);
02771 if(result)
02772 *result = r;
02773 if(r == ConvertGood)
02774 k.change(kc);
02775 else
02776 delete kc;
02777 return k;
02778 }
02779
02780 PGPKey PGPKey::fromString(const QString &s, ConvertResult *result, const QString &provider)
02781 {
02782 PGPKey k;
02783 PGPKeyContext *kc = static_cast<PGPKeyContext *>(getContext("pgpkey", provider));
02784 ConvertResult r = kc->fromAscii(s);
02785 if(result)
02786 *result = r;
02787 if(r == ConvertGood)
02788 k.change(kc);
02789 else
02790 delete kc;
02791 return k;
02792 }
02793
02794 PGPKey PGPKey::fromFile(const QString &fileName, ConvertResult *result, const QString &provider)
02795 {
02796 QString str;
02797 if(!stringFromFile(fileName, &str))
02798 {
02799 if(result)
02800 *result = ErrorFile;
02801 return PGPKey();
02802 }
02803 return fromString(str, result, provider);
02804 }
02805
02806
02807
02808
02809 class KeyLoaderThread : public QThread
02810 {
02811 Q_OBJECT
02812 public:
02813 enum Type { PKPEMFile, PKPEM, PKDER, KBDERFile, KBDER };
02814
02815 class In
02816 {
02817 public:
02818 Type type;
02819 QString fileName, pem;
02820 SecureArray der;
02821 QByteArray kbder;
02822 };
02823
02824 class Out
02825 {
02826 public:
02827 ConvertResult convertResult;
02828 PrivateKey privateKey;
02829 KeyBundle keyBundle;
02830 };
02831
02832 In in;
02833 Out out;
02834
02835 KeyLoaderThread(QObject *parent = 0) : QThread(parent)
02836 {
02837 }
02838
02839 protected:
02840 virtual void run()
02841 {
02842 if(in.type == PKPEMFile)
02843 out.privateKey = PrivateKey::fromPEMFile(in.fileName, SecureArray(), &out.convertResult);
02844 else if(in.type == PKPEM)
02845 out.privateKey = PrivateKey::fromPEM(in.pem, SecureArray(), &out.convertResult);
02846 else if(in.type == PKDER)
02847 out.privateKey = PrivateKey::fromDER(in.der, SecureArray(), &out.convertResult);
02848 else if(in.type == KBDERFile)
02849 out.keyBundle = KeyBundle::fromFile(in.fileName, SecureArray(), &out.convertResult);
02850 else if(in.type == KBDER)
02851 out.keyBundle = KeyBundle::fromArray(in.kbder, SecureArray(), &out.convertResult);
02852 }
02853 };
02854
02855 class KeyLoader::Private : public QObject
02856 {
02857 Q_OBJECT
02858 public:
02859 KeyLoader *q;
02860
02861 bool active;
02862 KeyLoaderThread *thread;
02863 KeyLoaderThread::In in;
02864 KeyLoaderThread::Out out;
02865
02866 Private(KeyLoader *_q) : QObject(_q), q(_q)
02867 {
02868 active = false;
02869 }
02870
02871 void reset()
02872 {
02873 in = KeyLoaderThread::In();
02874 out = KeyLoaderThread::Out();
02875 }
02876
02877 void start()
02878 {
02879 active = true;
02880 thread = new KeyLoaderThread(this);
02881
02882 connect(thread, SIGNAL(finished()), SLOT(thread_finished()), Qt::QueuedConnection);
02883 thread->in = in;
02884 thread->start();
02885 }
02886
02887 private slots:
02888 void thread_finished()
02889 {
02890 out = thread->out;
02891 delete thread;
02892 thread = 0;
02893 active = false;
02894
02895 emit q->finished();
02896 }
02897 };
02898
02899 KeyLoader::KeyLoader(QObject *parent)
02900 :QObject(parent)
02901 {
02902 d = new Private(this);
02903 }
02904
02905 KeyLoader::~KeyLoader()
02906 {
02907 delete d;
02908 }
02909
02910 void KeyLoader::loadPrivateKeyFromPEMFile(const QString &fileName)
02911 {
02912 Q_ASSERT(!d->active);
02913 if(d->active)
02914 return;
02915
02916 d->reset();
02917 d->in.type = KeyLoaderThread::PKPEMFile;
02918 d->in.fileName = fileName;
02919 d->start();
02920 }
02921
02922 void KeyLoader::loadPrivateKeyFromPEM(const QString &s)
02923 {
02924 Q_ASSERT(!d->active);
02925 if(d->active)
02926 return;
02927
02928 d->reset();
02929 d->in.type = KeyLoaderThread::PKPEM;
02930 d->in.pem = s;
02931 d->start();
02932 }
02933
02934 void KeyLoader::loadPrivateKeyFromDER(const SecureArray &a)
02935 {
02936 Q_ASSERT(!d->active);
02937 if(d->active)
02938 return;
02939
02940 d->reset();
02941 d->in.type = KeyLoaderThread::PKDER;
02942 d->in.der = a;
02943 d->start();
02944 }
02945
02946 void KeyLoader::loadKeyBundleFromFile(const QString &fileName)
02947 {
02948 Q_ASSERT(!d->active);
02949 if(d->active)
02950 return;
02951
02952 d->reset();
02953 d->in.type = KeyLoaderThread::KBDERFile;
02954 d->in.fileName = fileName;
02955 d->start();
02956 }
02957
02958 void KeyLoader::loadKeyBundleFromArray(const QByteArray &a)
02959 {
02960 Q_ASSERT(!d->active);
02961 if(d->active)
02962 return;
02963
02964 d->reset();
02965 d->in.type = KeyLoaderThread::KBDERFile;
02966 d->in.kbder = a;
02967 d->start();
02968 }
02969
02970 ConvertResult KeyLoader::convertResult() const
02971 {
02972 return d->out.convertResult;
02973 }
02974
02975 PrivateKey KeyLoader::privateKey() const
02976 {
02977 return d->out.privateKey;
02978 }
02979
02980 KeyBundle KeyLoader::keyBundle() const
02981 {
02982 return d->out.keyBundle;
02983 }
02984
02985 }
02986
02987 #include "qca_cert.moc"