/security/manager/ssl/src/nsNSSASN1Object.cpp

http://github.com/zpao/v8monkey · C++ · 463 lines · 340 code · 55 blank · 68 comment · 36 complexity · 5eef80c97a73d43043375712aab69e2a MD5 · raw file

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