Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

283 lines
8.2 KiB

  1. // X509Cert.cpp - Implementation of X509Cert class
  2. //
  3. // (c) Copyright Schlumberger Technology Corp., unpublished work, created
  4. // 1999. This computer program includes Confidential, Proprietary
  5. // Information and is a Trade Secret of Schlumberger Technology Corp. All
  6. // use, disclosure, and/or reproduction is prohibited unless authorized
  7. // in writing. All Rights Reserved.
  8. #include "pkiX509Cert.h"
  9. using namespace pki;
  10. X509Cert::X509Cert()
  11. {
  12. }
  13. X509Cert::X509Cert(const X509Cert &cert)
  14. {
  15. *this = cert;
  16. }
  17. X509Cert::X509Cert(const std::string &buffer)
  18. {
  19. *this = buffer;
  20. }
  21. X509Cert::X509Cert(const unsigned char *buffer, const unsigned long size)
  22. {
  23. m_Cert = BEROctet(buffer,size);
  24. Decode();
  25. }
  26. X509Cert& X509Cert::operator=(const X509Cert &cert)
  27. {
  28. m_Cert = cert.m_Cert;
  29. Decode();
  30. return *this;
  31. }
  32. X509Cert& X509Cert::operator=(const std::string &buffer)
  33. {
  34. m_Cert = BEROctet((unsigned char*)buffer.data(),buffer.size());
  35. Decode();
  36. return *this;
  37. }
  38. // Returns Serial Number (long) integer value.
  39. std::string X509Cert::SerialNumber() const
  40. {
  41. std::string RetVal((char*)m_SerialNumber.Data(),m_SerialNumber.DataSize());
  42. return RetVal;
  43. }
  44. // Returns whole DER string of Issuer
  45. std::string X509Cert::Issuer() const
  46. {
  47. std::string RetVal((char*)m_Issuer.Octet(),m_Issuer.OctetSize());
  48. return RetVal;
  49. }
  50. // Returns list of attributes in Issuer matching id-at-organizationName.
  51. // List will be invalidated when object changes.
  52. std::vector<std::string> X509Cert::IssuerOrg() const
  53. {
  54. std::vector<std::string> orgNames;
  55. std::vector<BEROctet const*> orgOcts;
  56. m_Issuer.SearchOIDNext("2 5 4 10",orgOcts); // Issuer's id-at-organizationName
  57. for(long i=0; i<orgOcts.size(); i++) {
  58. std::string oName((char*)orgOcts[i]->Data(), orgOcts[i]->DataSize());
  59. orgNames.push_back(oName);
  60. }
  61. return orgNames;
  62. }
  63. // Returns whole DER string of Subject
  64. std::string X509Cert::Subject() const
  65. {
  66. std::string RetVal((char*)m_Subject.Octet(),m_Subject.OctetSize());
  67. return RetVal;
  68. }
  69. // Returns list of attributes in Subject matching id-at-commonName
  70. // List will be invalidated when object changes.
  71. std::vector<std::string> X509Cert::SubjectCommonName() const
  72. {
  73. std::vector<std::string> cnNames;
  74. std::vector<BEROctet const*> cnOcts;
  75. m_Subject.SearchOIDNext("2 5 4 3",cnOcts); // Subject's id-at-commonName
  76. for(long i=0; i<cnOcts.size(); i++) {
  77. std::string cnName((char*)cnOcts[i]->Data(), cnOcts[i]->DataSize());
  78. cnNames.push_back(cnName);
  79. }
  80. return cnNames;
  81. }
  82. // Returns modulus from SubjectPublicKeyInfo, stripped for any leading zero(s).
  83. std::string X509Cert::Modulus() const
  84. {
  85. std::string RawMod = RawModulus();
  86. unsigned long i = 0;
  87. while(!RawMod[i] && i<RawMod.size()) i++; // Skip leading zero(s).
  88. return std::string(&RawMod[i],RawMod.size()-i);
  89. }
  90. // Returns public exponent from SubjectPublicKeyInfo, possibly with leading zero(s).
  91. std::string X509Cert::RawModulus() const
  92. {
  93. if(m_SubjectPublicKeyInfo.SubOctetList().size()!=2) throw Exception(ccX509CertFormatError);
  94. BEROctet PubKeyString = *(m_SubjectPublicKeyInfo.SubOctetList()[1]);
  95. unsigned char *KeyBlob = PubKeyString.Data();
  96. unsigned long KeyBlobSize = PubKeyString.DataSize();
  97. if(KeyBlob[0]) throw Exception(ccX509CertFormatError); // Expect number of unused bits in
  98. // last octet to be zero.
  99. KeyBlob++;
  100. KeyBlobSize--;
  101. BEROctet PubKeyOct(KeyBlob,KeyBlobSize);
  102. if(PubKeyOct.SubOctetList().size()!=2) throw Exception(ccX509CertFormatError);
  103. unsigned char *Mod = PubKeyOct.SubOctetList()[0]->Data();
  104. unsigned long ModSize = PubKeyOct.SubOctetList()[0]->DataSize();
  105. return std::string((char*)Mod,ModSize);
  106. }
  107. // Returns public exponent from SubjectPublicKeyInfo, stripped for any leading zero(s).
  108. std::string X509Cert::PublicExponent() const
  109. {
  110. std::string RawPubExp = RawPublicExponent();
  111. unsigned long i = 0;
  112. while(!RawPubExp[i] && i<RawPubExp.size()) i++; // Skip leading zero(s).
  113. return std::string(&RawPubExp[i],RawPubExp.size()-i);
  114. }
  115. // Returns public exponent from SubjectPublicKeyInfo, possibly with leading zero(s).
  116. std::string X509Cert::RawPublicExponent() const
  117. {
  118. if(m_SubjectPublicKeyInfo.SubOctetList().size()!=2) throw Exception(ccX509CertFormatError);
  119. BEROctet PubKeyString = *(m_SubjectPublicKeyInfo.SubOctetList()[1]);
  120. unsigned char *KeyBlob = PubKeyString.Data();
  121. unsigned long KeyBlobSize = PubKeyString.DataSize();
  122. if(KeyBlob[0]) throw Exception(ccX509CertFormatError); // Expect number of unused bits
  123. // in last octet to be zero.
  124. KeyBlob++;
  125. KeyBlobSize--;
  126. BEROctet PubKeyOct(KeyBlob,KeyBlobSize);
  127. if(PubKeyOct.SubOctetList().size()!=2) throw Exception(ccX509CertFormatError);
  128. unsigned char *PubExp = PubKeyOct.SubOctetList()[1]->Data();
  129. unsigned long PubExpSize = PubKeyOct.SubOctetList()[1]->DataSize();
  130. return std::string((char*)PubExp,PubExpSize);
  131. }
  132. // Returns KeyUsage attribute, left justified with most significant bit as first bit (BER convention)
  133. unsigned long X509Cert::KeyUsage() const
  134. {
  135. if(!m_Extensions.Octet()) throw Exception(ccX509CertExtensionNotPresent);
  136. unsigned long ReturnKeyUsage = 0;
  137. const unsigned char UnusedBitsMask[] = {0xFF,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80};
  138. std::vector<BEROctet const*> ExtensionList;
  139. m_Extensions.SearchOID("2 5 29 15",ExtensionList); // "Extensions" octets containing id-ce-keyUsage
  140. if(ExtensionList.size()!=1) throw Exception(ccX509CertExtensionNotPresent); // One and only one instance
  141. BEROctet const* Extension = ExtensionList[0];
  142. BEROctet* extnValue = 0;
  143. if(Extension->SubOctetList().size()==2) extnValue = Extension->SubOctetList()[1]; // No "critical" attribute present
  144. else if(Extension->SubOctetList().size()==3) extnValue = Extension->SubOctetList()[2]; // A "critical" attribute present
  145. else throw Exception(ccX509CertFormatError); // "Extensions" must contain either 2 or 3 octets
  146. unsigned char *KeyUsageBlob = extnValue->Data();
  147. unsigned long KeyUsageBlobSize = extnValue->DataSize();
  148. BEROctet KeyUsage(KeyUsageBlob,KeyUsageBlobSize);
  149. unsigned char *KeyUsageBitString = KeyUsage.Data();
  150. unsigned long KeyUsageBitStringSize = KeyUsage.DataSize();
  151. unsigned char UnusedBits = KeyUsageBitString[0];
  152. unsigned long NumBytes = KeyUsageBitStringSize-1;
  153. if(NumBytes>4) {
  154. NumBytes = 4; // Truncate to fit the ulong, should be plenty though
  155. UnusedBits = 0;
  156. }
  157. unsigned long Shift = 24;
  158. for(unsigned long i=0; i<NumBytes-1; i++) {
  159. ReturnKeyUsage |= (KeyUsageBitString[i+1] << Shift);
  160. Shift -= 8;
  161. }
  162. ReturnKeyUsage |= ( (KeyUsageBitString[NumBytes] & UnusedBitsMask[UnusedBits]) << Shift );
  163. return ReturnKeyUsage;
  164. }
  165. void X509Cert::Decode()
  166. {
  167. if(m_Cert.SubOctetList().size()!=3) throw Exception(ccX509CertFormatError);
  168. BEROctet *tbsCert = m_Cert.SubOctetList()[0];
  169. unsigned long Size = tbsCert->SubOctetList().size();
  170. if(!Size) throw Exception(ccX509CertFormatError);
  171. int i = 0;
  172. BEROctet *first = tbsCert->SubOctetList()[i];
  173. if((first->Class()==2) && (first->Tag()==0)) i++; // Version
  174. if(Size < (6+i)) throw Exception(ccX509CertFormatError);
  175. m_SerialNumber = *(tbsCert->SubOctetList()[i]); i++; // SerialNumber
  176. i++; // Signature (algorithm)
  177. m_Issuer = *(tbsCert->SubOctetList()[i]); i++; // Issuer
  178. i++; // Validity
  179. m_Subject = *(tbsCert->SubOctetList()[i]); i++; // Subject
  180. m_SubjectPublicKeyInfo = *(tbsCert->SubOctetList()[i]); i++; // SubjectPublicKeyInfo
  181. m_Extensions = BEROctet();
  182. while(i<Size) {
  183. BEROctet *oct = tbsCert->SubOctetList()[i];
  184. if((oct->Class()==2) && (oct->Tag()==3)) {
  185. m_Extensions = *oct;
  186. break;
  187. }
  188. i++;
  189. }
  190. }