]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. | |
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 | */ | |
26 | ||
27 | #include <TargetConditionals.h> | |
28 | #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) | |
29 | ||
30 | #include "SecNssCoder.h" | |
31 | #include <Security/cssmerr.h> | |
32 | #include <security_utilities/utilities.h> | |
33 | #include <security_asn1/secasn1.h> | |
34 | #include <string.h> | |
35 | #include <assert.h> | |
36 | ||
37 | #ifdef NDEBUG | |
38 | #define THROW_ENABLE 1 | |
39 | #else | |
40 | /* disable link against Security framework when true */ | |
41 | #define THROW_ENABLE 0 | |
42 | #endif | |
43 | ||
44 | #if THROW_ENABLE | |
45 | #define THROW_ERROR Security::CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR) | |
46 | #else | |
47 | #define THROW_ERROR | |
48 | #endif | |
49 | ||
50 | SecNssCoder::SecNssCoder(PRUint32 chunkSize /* = SNC_CHUNKSIZE_DEF */) | |
51 | : mPool(NULL) | |
52 | { | |
53 | mPool = PORT_NewArena(chunkSize); | |
54 | if(mPool == NULL) { | |
55 | THROW_ERROR; | |
56 | } | |
57 | } | |
58 | ||
59 | SecNssCoder::~SecNssCoder() | |
60 | { | |
61 | if(mPool != NULL) { | |
62 | /* | |
63 | * Note: we're asking for a memory zero here, but | |
64 | * PORT_FreeArena doesn't do that (yet). | |
65 | */ | |
66 | PORT_FreeArena(mPool, PR_TRUE); | |
67 | mPool = NULL; | |
68 | } | |
69 | } | |
70 | ||
71 | PRErrorCode SecNssCoder::decode( | |
72 | const void *src, // BER-encoded source | |
73 | size_t len, | |
74 | const SecAsn1Template *templ, | |
75 | void *dest) | |
76 | { | |
77 | SECStatus prtn; | |
78 | ||
79 | assert(mPool != NULL); | |
80 | prtn = SEC_ASN1Decode(mPool, dest, templ, (const char *)src, len); | |
81 | if(prtn) { | |
82 | return PR_GetError(); | |
83 | } | |
84 | else { | |
85 | return 0; | |
86 | } | |
87 | } | |
88 | ||
89 | PRErrorCode SecNssCoder::encodeItem( | |
90 | const void *src, | |
91 | const SecAsn1Template *templ, | |
92 | SECItem &dest) | |
93 | { | |
94 | assert(mPool != NULL); | |
95 | ||
96 | dest.Data = NULL; | |
97 | dest.Length = 0; | |
98 | ||
99 | SECItem *rtnItem = SEC_ASN1EncodeItem(mPool, &dest, src, templ); | |
100 | if(rtnItem == NULL) { | |
101 | return PR_GetError(); | |
102 | } | |
103 | else { | |
104 | return 0; | |
105 | } | |
106 | } | |
107 | ||
108 | void *SecNssCoder::malloc(size_t len) | |
109 | { | |
110 | assert(mPool != NULL); | |
111 | void *rtn = PORT_ArenaAlloc(mPool, len); | |
112 | if(rtn == NULL) { | |
113 | THROW_ERROR; | |
114 | } | |
115 | return rtn; | |
116 | } | |
117 | ||
118 | /* malloc item.Data, set item.Length */ | |
119 | void SecNssCoder::allocItem( | |
120 | SECItem &item, | |
121 | size_t len) | |
122 | { | |
123 | item.Data = (uint8 *)malloc(len); | |
124 | item.Length = len; | |
125 | } | |
126 | ||
127 | /* malloc and copy */ | |
128 | void SecNssCoder::allocCopyItem( | |
129 | const void *src, | |
130 | size_t len, | |
131 | SECItem &dest) | |
132 | { | |
133 | allocItem(dest, len); | |
134 | memmove(dest.Data, src, len); | |
135 | } | |
136 | ||
137 | /* | |
138 | * This is pretty much a copy of SEC_ASN1EncodeItem, with a Allocator | |
139 | * malloc replacing the sec_asn1e_allocate_item to alloc the output data. | |
140 | */ | |
141 | PRErrorCode SecNssEncodeItem( | |
142 | const void *src, | |
143 | const SecAsn1Template *templ, | |
144 | Security::Allocator &alloc, | |
145 | SECItem &dest) | |
146 | { | |
147 | unsigned long encoding_length = 0; | |
148 | SECStatus rv; | |
149 | ||
150 | dest.Data = NULL; | |
151 | dest.Length = 0; | |
152 | ||
153 | rv = SEC_ASN1Encode (src, templ, | |
154 | sec_asn1e_encode_item_count, &encoding_length); | |
155 | if (rv != SECSuccess) { | |
156 | return PR_GetError(); | |
157 | } | |
158 | ||
159 | /* replace this... | |
160 | dest = sec_asn1e_allocate_item (poolp, dest, encoding_length); | |
161 | if (dest == NULL) | |
162 | return NULL; | |
163 | ... with this: */ | |
164 | dest.Data = (uint8 *)alloc.malloc(encoding_length); | |
165 | dest.Length = 0; | |
166 | /* end replacement */ | |
167 | ||
168 | rv = SEC_ASN1Encode (src, templ, sec_asn1e_encode_item_store, &dest); | |
169 | if (rv != SECSuccess) { | |
170 | return PR_GetError(); | |
171 | } | |
172 | ||
173 | assert(encoding_length == dest.Length); | |
174 | return 0; | |
175 | } | |
176 | ||
177 | PRErrorCode SecNssEncodeItemOdata( | |
178 | const void *src, | |
179 | const SecAsn1Template *templ, | |
180 | CssmOwnedData &odata) | |
181 | { | |
182 | Allocator &alloc = odata.allocator; | |
183 | SECItem sitem; | |
184 | PRErrorCode prtn; | |
185 | ||
186 | prtn = SecNssEncodeItem(src, templ, alloc, sitem); | |
187 | if(prtn) { | |
188 | return prtn; | |
189 | } | |
190 | odata.set(sitem.Data, sitem.Length); | |
191 | return 0; | |
192 | } | |
193 | ||
194 | #endif /* TARGET_OS_MAC */ |