]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2003-2005 Apple Computer, Inc. All Rights Reserved. |
b1ab9ed8 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | * | |
23 | * SecNssCoder.cpp: simple C++ wrapper for PLArenaPool and the | |
24 | * high-level ANS1 encode/decode routines. | |
25 | */ | |
d8f41ccd | 26 | |
b1ab9ed8 A |
27 | #include "SecNssCoder.h" |
28 | #include <Security/cssmerr.h> | |
29 | #include <security_utilities/utilities.h> | |
30 | #include <security_asn1/secasn1.h> | |
31 | #include <string.h> | |
32 | #include <assert.h> | |
33 | ||
34 | #ifdef NDEBUG | |
35 | #define THROW_ENABLE 1 | |
36 | #else | |
37 | /* disable link against Security framework when true */ | |
38 | #define THROW_ENABLE 0 | |
39 | #endif | |
40 | ||
41 | #if THROW_ENABLE | |
42 | #define THROW_ERROR Security::CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR) | |
43 | #else | |
44 | #define THROW_ERROR | |
45 | #endif | |
46 | ||
47 | SecNssCoder::SecNssCoder(PRUint32 chunkSize /* = SNC_CHUNKSIZE_DEF */) | |
48 | : mPool(NULL) | |
49 | { | |
50 | mPool = PORT_NewArena(chunkSize); | |
51 | if(mPool == NULL) { | |
52 | THROW_ERROR; | |
53 | } | |
54 | } | |
55 | ||
56 | SecNssCoder::~SecNssCoder() | |
57 | { | |
58 | if(mPool != NULL) { | |
59 | /* | |
60 | * Note: we're asking for a memory zero here, but | |
61 | * PORT_FreeArena doesn't do that (yet). | |
62 | */ | |
63 | PORT_FreeArena(mPool, PR_TRUE); | |
64 | mPool = NULL; | |
65 | } | |
66 | } | |
67 | ||
68 | PRErrorCode SecNssCoder::decode( | |
69 | const void *src, // BER-encoded source | |
d8f41ccd | 70 | unsigned long len, |
b1ab9ed8 A |
71 | const SecAsn1Template *templ, |
72 | void *dest) | |
73 | { | |
74 | SECStatus prtn; | |
75 | ||
76 | assert(mPool != NULL); | |
77 | prtn = SEC_ASN1Decode(mPool, dest, templ, (const char *)src, len); | |
78 | if(prtn) { | |
79 | return PR_GetError(); | |
80 | } | |
81 | else { | |
82 | return 0; | |
83 | } | |
84 | } | |
85 | ||
86 | PRErrorCode SecNssCoder::encodeItem( | |
87 | const void *src, | |
88 | const SecAsn1Template *templ, | |
89 | SECItem &dest) | |
90 | { | |
91 | assert(mPool != NULL); | |
92 | ||
93 | dest.Data = NULL; | |
94 | dest.Length = 0; | |
95 | ||
96 | SECItem *rtnItem = SEC_ASN1EncodeItem(mPool, &dest, src, templ); | |
97 | if(rtnItem == NULL) { | |
98 | return PR_GetError(); | |
99 | } | |
100 | else { | |
101 | return 0; | |
102 | } | |
103 | } | |
104 | ||
105 | void *SecNssCoder::malloc(size_t len) | |
106 | { | |
107 | assert(mPool != NULL); | |
108 | void *rtn = PORT_ArenaAlloc(mPool, len); | |
109 | if(rtn == NULL) { | |
110 | THROW_ERROR; | |
111 | } | |
112 | return rtn; | |
113 | } | |
114 | ||
115 | /* malloc item.Data, set item.Length */ | |
116 | void SecNssCoder::allocItem( | |
117 | SECItem &item, | |
118 | size_t len) | |
119 | { | |
120 | item.Data = (uint8 *)malloc(len); | |
121 | item.Length = len; | |
122 | } | |
123 | ||
124 | /* malloc and copy */ | |
125 | void SecNssCoder::allocCopyItem( | |
126 | const void *src, | |
127 | size_t len, | |
128 | SECItem &dest) | |
129 | { | |
130 | allocItem(dest, len); | |
131 | memmove(dest.Data, src, len); | |
132 | } | |
133 | ||
134 | /* | |
135 | * This is pretty much a copy of SEC_ASN1EncodeItem, with a Allocator | |
136 | * malloc replacing the sec_asn1e_allocate_item to alloc the output data. | |
137 | */ | |
138 | PRErrorCode SecNssEncodeItem( | |
139 | const void *src, | |
140 | const SecAsn1Template *templ, | |
141 | Security::Allocator &alloc, | |
142 | SECItem &dest) | |
143 | { | |
144 | unsigned long encoding_length = 0; | |
145 | SECStatus rv; | |
146 | ||
147 | dest.Data = NULL; | |
148 | dest.Length = 0; | |
149 | ||
150 | rv = SEC_ASN1Encode (src, templ, | |
151 | sec_asn1e_encode_item_count, &encoding_length); | |
152 | if (rv != SECSuccess) { | |
153 | return PR_GetError(); | |
154 | } | |
155 | ||
156 | /* replace this... | |
157 | dest = sec_asn1e_allocate_item (poolp, dest, encoding_length); | |
158 | if (dest == NULL) | |
159 | return NULL; | |
160 | ... with this: */ | |
161 | dest.Data = (uint8 *)alloc.malloc(encoding_length); | |
162 | dest.Length = 0; | |
163 | /* end replacement */ | |
164 | ||
165 | rv = SEC_ASN1Encode (src, templ, sec_asn1e_encode_item_store, &dest); | |
166 | if (rv != SECSuccess) { | |
167 | return PR_GetError(); | |
168 | } | |
169 | ||
170 | assert(encoding_length == dest.Length); | |
171 | return 0; | |
172 | } | |
173 | ||
174 | PRErrorCode SecNssEncodeItemOdata( | |
175 | const void *src, | |
176 | const SecAsn1Template *templ, | |
177 | CssmOwnedData &odata) | |
178 | { | |
179 | Allocator &alloc = odata.allocator; | |
180 | SECItem sitem; | |
181 | PRErrorCode prtn; | |
182 | ||
183 | prtn = SecNssEncodeItem(src, templ, alloc, sitem); | |
184 | if(prtn) { | |
185 | return prtn; | |
186 | } | |
187 | odata.set(sitem.Data, sitem.Length); | |
188 | return 0; | |
189 | } | |
190 | ||
d8f41ccd | 191 |