]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/c++-lib/src/cdsaUtils.cpp
d9b9fc82f7b7765a504eee5f1955efc6af5eb41c
[apple/security.git] / SecuritySNACCRuntime / c++-lib / src / cdsaUtils.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 * cdsaUtils.cpp - utility functions for CDSA-related code
21 */
22
23 #include "cdsaUtils.h"
24 #include <Security/cssmerr.h>
25
26 #ifdef NDEBUG
27
28 #include <Security/globalizer.h>
29
30 /* silent cerr substitute */
31 ModuleNexus<Asn1ErrorClass> AsnNullError;
32 #endif /* NDEBUG */
33
34 /* malloc/copy AsnBits.bits -->CssmOwnedData */
35 void SC_asnBitsToCssmData(
36 const AsnBits &bits,
37 CssmOwnedData &oData)
38 {
39 size_t len = (bits.BitLen() + 7) / 8;
40 oData.copy(reinterpret_cast<const uint8 *>(bits.BitOcts()), len);
41 }
42
43 /* given DER-encoded bit string, decoded it and malloc/copy results
44 * back to a CssmOwnedData */
45 void SC_decodeAsnBitsToCssmData(
46 const CssmData encodedBits,
47 CssmOwnedData &oData)
48 {
49 AsnBits decodedBits;
50 SC_decodeAsnObj(encodedBits, decodedBits);
51 size_t len = (decodedBits.BitLen() + 7) / 8;
52 oData.copy(reinterpret_cast<const uint8 *>(decodedBits.BitOcts()), len);
53 }
54
55 /*
56 * Universal BDecPdu/BEncPdu replacements, used below in SC_decodeAsnObj and
57 * SC_encodeAsnObj.
58 *
59 * All AsnType subclasses implement this either via PDU_MEMBER_MACROS
60 * for SecuritySNACCRuntime built-in types, or explicitly for all
61 * other classes using asn-useful.h. To faciliate a global "one
62 * routine for encode/decode" which operattes on AsnType &'s, we have
63 * to explicitly provide this here. Why this is no in AsnType, I don't
64 * know.
65 */
66 static int SC_BDecPDU(
67 AsnType &asnObj,
68 BUF_TYPE b,
69 AsnLen &bytesDecoded)
70 {
71 ENV_TYPE env;
72 int val;
73
74 bytesDecoded = 0;
75 if ((val = setjmp (env)) == 0)
76 {
77 asnObj.BDec(b, bytesDecoded, env);
78 return !b.ReadError();
79 }
80 else
81 return false;
82 }
83
84 static int SC_BEncPdu(
85 AsnType &asnObj,
86 BUF_TYPE b,
87 AsnLen &bytesEncoded)
88 {
89 bytesEncoded = asnObj.BEnc(b);
90 return !b.WriteError();
91 }
92
93 /* DER-decode any AsnType object */
94 void SC_decodeAsnObj(
95 const CssmData &derEncoded,
96 AsnType &asnObj)
97 {
98 AsnBuf buf;
99 size_t len = (size_t)derEncoded.length();
100
101 buf.InstallData(reinterpret_cast<char *>(derEncoded.data()), len);
102 if(!SC_BDecPDU(asnObj, buf, len)) {
103 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
104 }
105 }
106
107 /*
108 * DER-encode any AsnType object.
109 * Unfortunately the call has to give an estimate of the max encoded size of
110 * the result. There is no way (that I know of) to figure this out at encode
111 * time. If this turns out to be a problem we might have to do a retry,
112 * doubling the size of the encoded buffer. Be liberal; the maxEncodedSize
113 * buffer is only temporary - due to snacc encoding style, a copy out is
114 * necessary in any case, so the mallocd size of encodedBuf is exactly the
115 * right size.
116 */
117 void SC_encodeAsnObj(
118 AsnType &asnObj,
119 CssmOwnedData &derEncoded,
120 size_t maxEncodedSize)
121 {
122 CssmAutoData aData(derEncoded.allocator); // temp encode target
123 aData.malloc(maxEncodedSize);
124 memset(aData.data(), 0, maxEncodedSize);
125 AsnBuf encBuf;
126 encBuf.Init(static_cast<char *>(aData.data()), maxEncodedSize);
127 encBuf.ResetInWriteRvsMode();
128 AsnLen encoded;
129 int rtn = SC_BEncPdu(asnObj, encBuf, encoded);
130 if(encoded > maxEncodedSize) {
131 CssmError::throwMe(CSSMERR_CSSM_BUFFER_TOO_SMALL);
132 }
133 if(!rtn) {
134 /* not sure how this can happen... */
135 CssmError::throwMe(CSSMERR_CSSM_BUFFER_TOO_SMALL);
136 }
137 /* success; copy out to caller */
138 derEncoded.get().clear();
139 derEncoded.copy(encBuf.DataPtr(), encBuf.DataLen());
140 }
141
142 /*
143 * Given a contentLength, obtain the length of the DER length encoding.
144 */
145 size_t SC_lengthOfLength(
146 size_t contentLen)
147 {
148 if(contentLen < 128) {
149 return 1;
150 }
151 else if(contentLen < 256) {
152 return 2;
153 }
154 else if(contentLen < 65536) {
155 return 3;
156 }
157 else if(contentLen < 16777126) {
158 return 4;
159 }
160 else {
161 return 5;
162 }
163 }
164
165 /*
166 * Encode a DER length field. Pass in the lengthOfLength if you've obtained
167 * it in a previous call to SC_lengthOfLength.
168 */
169 void SC_encodeLength(
170 size_t contentLen,
171 void *cp,
172 size_t lengthOfLength)
173 {
174 if(lengthOfLength == 0) {
175 lengthOfLength = SC_lengthOfLength(contentLen);
176 }
177 unsigned char *ucp = reinterpret_cast<unsigned char *>(cp);
178 if(lengthOfLength == 1) {
179 /* easy case */
180 *ucp = contentLen;
181 return;
182 }
183 lengthOfLength--;
184 *ucp = (0x80 + lengthOfLength);
185 ucp += lengthOfLength;
186 for(size_t i=0; i<lengthOfLength; i++) {
187 *ucp-- = contentLen & 0xff;
188 contentLen >>= 8;
189 }
190 }