nsNSSASN1Object.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #include "nsNSSASN1Object.h"
  5. #include "nsArray.h"
  6. #include "nsArrayUtils.h"
  7. #include "nsIComponentManager.h"
  8. #include "nsReadableUtils.h"
  9. #include "nsXPCOMCID.h"
  10. #include "secasn1.h"
  11. NS_IMPL_ISUPPORTS(nsNSSASN1Sequence, nsIASN1Sequence, nsIASN1Object)
  12. NS_IMPL_ISUPPORTS(nsNSSASN1PrintableItem, nsIASN1PrintableItem, nsIASN1Object)
  13. // This function is used to interpret an integer that
  14. // was encoded in a DER buffer. This function is used
  15. // when converting a DER buffer into a nsIASN1Object
  16. // structure. This interprets the buffer in data
  17. // as defined by the DER (Distinguised Encoding Rules) of
  18. // ASN1.
  19. static int
  20. getInteger256(unsigned char *data, unsigned int nb)
  21. {
  22. int val;
  23. switch (nb) {
  24. case 1:
  25. val = data[0];
  26. break;
  27. case 2:
  28. val = (data[0] << 8) | data[1];
  29. break;
  30. case 3:
  31. val = (data[0] << 16) | (data[1] << 8) | data[2];
  32. break;
  33. case 4:
  34. val = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
  35. break;
  36. default:
  37. return -1;
  38. }
  39. return val;
  40. }
  41. // This function is used to retrieve the lenght of a DER encoded
  42. // item. It looks to see if this a multibyte length and then
  43. // interprets the buffer accordingly to get the actual length value.
  44. // This funciton is used mostly while parsing the DER headers.
  45. //
  46. // A DER encoded item has the following structure:
  47. //
  48. // <tag><length<data consisting of lenght bytes>
  49. static int32_t
  50. getDERItemLength(unsigned char *data, unsigned char *end,
  51. unsigned long *bytesUsed, bool *indefinite)
  52. {
  53. unsigned char lbyte = *data++;
  54. int32_t length = -1;
  55. *indefinite = false;
  56. if (lbyte >= 0x80) {
  57. // Multibyte length
  58. unsigned nb = (unsigned) (lbyte & 0x7f);
  59. if (nb > 4) {
  60. return -1;
  61. }
  62. if (nb > 0) {
  63. if ((data+nb) > end) {
  64. return -1;
  65. }
  66. length = getInteger256(data, nb);
  67. if (length < 0)
  68. return -1;
  69. } else {
  70. *indefinite = true;
  71. length = 0;
  72. }
  73. *bytesUsed = nb+1;
  74. } else {
  75. length = lbyte;
  76. *bytesUsed = 1;
  77. }
  78. return length;
  79. }
  80. static nsresult
  81. buildASN1ObjectFromDER(unsigned char *data,
  82. unsigned char *end,
  83. nsIASN1Sequence *parent)
  84. {
  85. nsresult rv;
  86. nsCOMPtr<nsIASN1Sequence> sequence;
  87. nsCOMPtr<nsIASN1PrintableItem> printableItem;
  88. nsCOMPtr<nsIASN1Object> asn1Obj;
  89. nsCOMPtr<nsIMutableArray> parentObjects;
  90. NS_ENSURE_ARG_POINTER(parent);
  91. if (data >= end)
  92. return NS_OK;
  93. unsigned char code, tagnum;
  94. // A DER item has the form of |tag|len|data
  95. // tag is one byte and describes the type of element
  96. // we are dealing with.
  97. // len is a DER encoded int telling us how long the data is
  98. // data is a buffer that is len bytes long and has to be
  99. // interpreted according to its type.
  100. unsigned long bytesUsed;
  101. bool indefinite;
  102. int32_t len;
  103. uint32_t type;
  104. rv = parent->GetASN1Objects(getter_AddRefs(parentObjects));
  105. if (NS_FAILED(rv) || !parentObjects)
  106. return NS_ERROR_FAILURE;
  107. while (data < end) {
  108. code = *data;
  109. tagnum = code & SEC_ASN1_TAGNUM_MASK;
  110. /*
  111. * NOTE: This code does not (yet) handle the high-tag-number form!
  112. */
  113. if (tagnum == SEC_ASN1_HIGH_TAG_NUMBER) {
  114. return NS_ERROR_FAILURE;
  115. }
  116. data++;
  117. len = getDERItemLength(data, end, &bytesUsed, &indefinite);
  118. if (len < 0) {
  119. return NS_ERROR_FAILURE;
  120. }
  121. data += bytesUsed;
  122. if (data + len > end) {
  123. return NS_ERROR_FAILURE;
  124. }
  125. if (code & SEC_ASN1_CONSTRUCTED) {
  126. if (len > 0 || indefinite) {
  127. sequence = new nsNSSASN1Sequence();
  128. switch (code & SEC_ASN1_CLASS_MASK) {
  129. case SEC_ASN1_UNIVERSAL:
  130. type = tagnum;
  131. break;
  132. case SEC_ASN1_APPLICATION:
  133. type = nsIASN1Object::ASN1_APPLICATION;
  134. break;
  135. case SEC_ASN1_CONTEXT_SPECIFIC:
  136. type = nsIASN1Object::ASN1_CONTEXT_SPECIFIC;
  137. break;
  138. case SEC_ASN1_PRIVATE:
  139. type = nsIASN1Object::ASN1_PRIVATE;
  140. break;
  141. default:
  142. NS_ERROR("Bad DER");
  143. return NS_ERROR_FAILURE;
  144. }
  145. sequence->SetTag(tagnum);
  146. sequence->SetType(type);
  147. rv = buildASN1ObjectFromDER(data, (len == 0) ? end : data + len,
  148. sequence);
  149. asn1Obj = sequence;
  150. }
  151. } else {
  152. printableItem = new nsNSSASN1PrintableItem();
  153. asn1Obj = printableItem;
  154. asn1Obj->SetType(tagnum);
  155. asn1Obj->SetTag(tagnum);
  156. printableItem->SetData((char*)data, len);
  157. }
  158. data += len;
  159. parentObjects->AppendElement(asn1Obj, false);
  160. }
  161. return NS_OK;
  162. }
  163. nsresult
  164. CreateFromDER(unsigned char *data,
  165. unsigned int len,
  166. nsIASN1Object **retval)
  167. {
  168. nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence;
  169. *retval = nullptr;
  170. nsresult rv = buildASN1ObjectFromDER(data, data+len, sequence);
  171. if (NS_SUCCEEDED(rv)) {
  172. // The actual object will be the first element inserted
  173. // into the sequence of the sequence variable we created.
  174. nsCOMPtr<nsIMutableArray> elements;
  175. sequence->GetASN1Objects(getter_AddRefs(elements));
  176. nsCOMPtr<nsIASN1Object> asn1Obj = do_QueryElementAt(elements, 0);
  177. if (!asn1Obj) {
  178. return NS_ERROR_FAILURE;
  179. }
  180. asn1Obj.forget(retval);
  181. }
  182. return rv;
  183. }
  184. nsNSSASN1Sequence::nsNSSASN1Sequence() : mType(0),
  185. mTag(0),
  186. mIsValidContainer(true),
  187. mIsExpanded(true)
  188. {
  189. /* member initializers and constructor code */
  190. }
  191. nsNSSASN1Sequence::~nsNSSASN1Sequence()
  192. {
  193. /* destructor code */
  194. }
  195. NS_IMETHODIMP
  196. nsNSSASN1Sequence::GetASN1Objects(nsIMutableArray * *aASN1Objects)
  197. {
  198. if (!mASN1Objects) {
  199. mASN1Objects = nsArrayBase::Create();
  200. }
  201. *aASN1Objects = mASN1Objects;
  202. NS_IF_ADDREF(*aASN1Objects);
  203. return NS_OK;
  204. }
  205. NS_IMETHODIMP
  206. nsNSSASN1Sequence::SetASN1Objects(nsIMutableArray * aASN1Objects)
  207. {
  208. mASN1Objects = aASN1Objects;
  209. return NS_OK;
  210. }
  211. NS_IMETHODIMP
  212. nsNSSASN1Sequence::GetTag(uint32_t *aTag)
  213. {
  214. *aTag = mTag;
  215. return NS_OK;
  216. }
  217. NS_IMETHODIMP
  218. nsNSSASN1Sequence::SetTag(uint32_t aTag)
  219. {
  220. mTag = aTag;
  221. return NS_OK;
  222. }
  223. NS_IMETHODIMP
  224. nsNSSASN1Sequence::GetType(uint32_t *aType)
  225. {
  226. *aType = mType;
  227. return NS_OK;
  228. }
  229. NS_IMETHODIMP
  230. nsNSSASN1Sequence::SetType(uint32_t aType)
  231. {
  232. mType = aType;
  233. return NS_OK;
  234. }
  235. NS_IMETHODIMP
  236. nsNSSASN1Sequence::GetDisplayName(nsAString &aDisplayName)
  237. {
  238. aDisplayName = mDisplayName;
  239. return NS_OK;
  240. }
  241. NS_IMETHODIMP
  242. nsNSSASN1Sequence::SetDisplayName(const nsAString &aDisplayName)
  243. {
  244. mDisplayName = aDisplayName;
  245. return NS_OK;
  246. }
  247. NS_IMETHODIMP
  248. nsNSSASN1Sequence::GetDisplayValue(nsAString &aDisplayValue)
  249. {
  250. aDisplayValue = mDisplayValue;
  251. return NS_OK;
  252. }
  253. NS_IMETHODIMP
  254. nsNSSASN1Sequence::SetDisplayValue(const nsAString &aDisplayValue)
  255. {
  256. mDisplayValue = aDisplayValue;
  257. return NS_OK;
  258. }
  259. NS_IMETHODIMP
  260. nsNSSASN1Sequence::GetIsValidContainer(bool *aIsValidContainer)
  261. {
  262. NS_ENSURE_ARG_POINTER(aIsValidContainer);
  263. *aIsValidContainer = mIsValidContainer;
  264. return NS_OK;
  265. }
  266. NS_IMETHODIMP
  267. nsNSSASN1Sequence::SetIsValidContainer(bool aIsValidContainer)
  268. {
  269. mIsValidContainer = aIsValidContainer;
  270. SetIsExpanded(mIsValidContainer);
  271. return NS_OK;
  272. }
  273. NS_IMETHODIMP
  274. nsNSSASN1Sequence::GetIsExpanded(bool *aIsExpanded)
  275. {
  276. NS_ENSURE_ARG_POINTER(aIsExpanded);
  277. *aIsExpanded = mIsExpanded;
  278. return NS_OK;
  279. }
  280. NS_IMETHODIMP
  281. nsNSSASN1Sequence::SetIsExpanded(bool aIsExpanded)
  282. {
  283. mIsExpanded = aIsExpanded;
  284. return NS_OK;
  285. }
  286. nsNSSASN1PrintableItem::nsNSSASN1PrintableItem() : mType(0),
  287. mTag(0),
  288. mData(nullptr),
  289. mLen(0)
  290. {
  291. /* member initializers and constructor code */
  292. }
  293. nsNSSASN1PrintableItem::~nsNSSASN1PrintableItem()
  294. {
  295. /* destructor code */
  296. if (mData)
  297. free(mData);
  298. }
  299. NS_IMETHODIMP
  300. nsNSSASN1PrintableItem::GetDisplayValue(nsAString &aValue)
  301. {
  302. aValue = mValue;
  303. return NS_OK;
  304. }
  305. NS_IMETHODIMP
  306. nsNSSASN1PrintableItem::SetDisplayValue(const nsAString &aValue)
  307. {
  308. mValue = aValue;
  309. return NS_OK;
  310. }
  311. NS_IMETHODIMP
  312. nsNSSASN1PrintableItem::GetTag(uint32_t *aTag)
  313. {
  314. *aTag = mTag;
  315. return NS_OK;
  316. }
  317. NS_IMETHODIMP
  318. nsNSSASN1PrintableItem::SetTag(uint32_t aTag)
  319. {
  320. mTag = aTag;
  321. return NS_OK;
  322. }
  323. NS_IMETHODIMP
  324. nsNSSASN1PrintableItem::GetType(uint32_t *aType)
  325. {
  326. *aType = mType;
  327. return NS_OK;
  328. }
  329. NS_IMETHODIMP
  330. nsNSSASN1PrintableItem::SetType(uint32_t aType)
  331. {
  332. mType = aType;
  333. return NS_OK;
  334. }
  335. NS_IMETHODIMP
  336. nsNSSASN1PrintableItem::SetData(char *data, uint32_t len)
  337. {
  338. if (len > 0) {
  339. if (mLen < len) {
  340. unsigned char* newData = (unsigned char*)moz_xrealloc(mData, len);
  341. if (!newData)
  342. return NS_ERROR_OUT_OF_MEMORY;
  343. mData = newData;
  344. }
  345. memcpy(mData, data, len);
  346. } else if (len == 0) {
  347. if (mData) {
  348. free(mData);
  349. mData = nullptr;
  350. }
  351. }
  352. mLen = len;
  353. return NS_OK;
  354. }
  355. NS_IMETHODIMP
  356. nsNSSASN1PrintableItem::GetData(char **outData, uint32_t *outLen)
  357. {
  358. NS_ENSURE_ARG_POINTER(outData);
  359. NS_ENSURE_ARG_POINTER(outLen);
  360. *outData = (char*)mData;
  361. *outLen = mLen;
  362. return NS_OK;
  363. }
  364. NS_IMETHODIMP
  365. nsNSSASN1PrintableItem::GetDisplayName(nsAString &aDisplayName)
  366. {
  367. aDisplayName = mDisplayName;
  368. return NS_OK;
  369. }
  370. NS_IMETHODIMP
  371. nsNSSASN1PrintableItem::SetDisplayName(const nsAString &aDisplayName)
  372. {
  373. mDisplayName = aDisplayName;
  374. return NS_OK;
  375. }