]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / libsecurity_apple_csp / lib / RSA_asymmetric.cpp
1 /*
2 * Copyright (c) 2000-2001,2011-2012,2014 Apple 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 * RSA_asymmetric.cpp - CSPContext for RSA asymmetric encryption
21 */
22
23 #include "RSA_asymmetric.h"
24 #include "RSA_DSA_utils.h"
25 #include <security_utilities/debugging.h>
26 #include <opensslUtils/opensslUtils.h>
27
28 #define rsaCryptDebug(args...) secdebug("rsaCrypt", ## args)
29 #define rbprintf(args...) secdebug("rsaBuf", ## args)
30
31 static ModuleNexus<Mutex> gMutex;
32
33 RSA_CryptContext::~RSA_CryptContext()
34 {
35 StLock<Mutex> _(gMutex());
36 if(mAllocdRsaKey) {
37 assert(mRsaKey != NULL);
38 RSA_free(mRsaKey);
39 mRsaKey = NULL;
40 mAllocdRsaKey = false;
41 }
42 }
43
44 /* called by CSPFullPluginSession */
45 void RSA_CryptContext::init(const Context &context, bool encoding /*= true*/)
46 {
47 StLock<Mutex> _(gMutex());
48
49 if(mInitFlag && !opStarted()) {
50 /* reusing - e.g. query followed by encrypt */
51 return;
52 }
53
54 /* optional mode to use alternate key class (e.g., decrypt with public key) */
55 CSSM_KEYCLASS keyClass;
56 switch (context.getInt(CSSM_ATTRIBUTE_MODE)) {
57 case CSSM_ALGMODE_PUBLIC_KEY:
58 keyClass = CSSM_KEYCLASS_PUBLIC_KEY;
59 break;
60 case CSSM_ALGMODE_PRIVATE_KEY:
61 keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
62 break;
63 case CSSM_ALGMODE_NONE:
64 /* default, not present in context: infer from op type */
65 keyClass = encoding ? CSSM_KEYCLASS_PUBLIC_KEY : CSSM_KEYCLASS_PRIVATE_KEY;
66 break;
67 default:
68 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE);
69 }
70
71 /* fetch key from context */
72 if(mRsaKey == NULL) {
73 assert(!opStarted());
74 CSSM_DATA label = {0, NULL};
75 mRsaKey = contextToRsaKey(context,
76 session(),
77 keyClass,
78 encoding ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
79 mAllocdRsaKey,
80 label);
81 if(label.Data) {
82 mLabel.copy(label);
83 mOaep = true;
84 free(label.Data);
85 }
86 }
87 else {
88 assert(opStarted());
89 }
90
91 unsigned cipherBlockSize = RSA_size(mRsaKey);
92 unsigned plainBlockSize;
93
94 /* padding - not present means value zero, CSSM_PADDING_NONE */
95 uint32 padding = context.getInt(CSSM_ATTRIBUTE_PADDING);
96 switch(padding) {
97 case CSSM_PADDING_NONE:
98 mPadding = RSA_NO_PADDING;
99 plainBlockSize = cipherBlockSize;
100 break;
101 case CSSM_PADDING_PKCS1:
102 mPadding = RSA_PKCS1_PADDING;
103 plainBlockSize = cipherBlockSize - 11;
104 break;
105 case CSSM_PADDING_APPLE_SSLv2:
106 rsaCryptDebug("RSA_CryptContext::init using CSSM_PADDING_APPLE_SSLv2");
107 mPadding = RSA_SSLV23_PADDING;
108 plainBlockSize = cipherBlockSize - 11;
109 break;
110 default:
111 rsaCryptDebug("RSA_CryptContext::init bad padding (0x%x)",
112 (unsigned)padding);
113 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING);
114 }
115
116 /* optional blinding attribute */
117 uint32 blinding = context.getInt(CSSM_ATTRIBUTE_RSA_BLINDING);
118 if(blinding) {
119 if(RSA_blinding_on(mRsaKey, NULL) <= 0) {
120 /* actually no legit failures */
121 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
122 }
123 }
124 else {
125 RSA_blinding_off(mRsaKey);
126 }
127
128 /* finally, have BlockCryptor set up its stuff. */
129 setup(encoding ? plainBlockSize : cipherBlockSize, // blockSizeIn
130 encoding ? cipherBlockSize : plainBlockSize, // blockSizeOut
131 false, // pkcs5Pad
132 false, // needsFinal
133 BCM_ECB,
134 NULL); // IV
135 mInitFlag = true;
136
137 }
138 /* called by BlockCryptor */
139 void RSA_CryptContext::encryptBlock(
140 const void *plainText, // length implied (one block)
141 size_t plainTextLen,
142 void *cipherText,
143 size_t &cipherTextLen, // in/out, throws on overflow
144 bool final)
145 {
146 StLock<Mutex> _(gMutex());
147
148 int irtn;
149
150 /* FIXME do OAEP encoding here */
151 if(mRsaKey->d == NULL) {
152 irtn = RSA_public_encrypt((int)plainTextLen,
153 (unsigned char *)plainText,
154 (unsigned char *)cipherText,
155 mRsaKey,
156 mPadding);
157 }
158 else {
159 irtn = RSA_private_encrypt((int)plainTextLen,
160 (unsigned char *)plainText,
161 (unsigned char *)cipherText,
162 mRsaKey,
163 mPadding);
164 }
165 if(irtn < 0) {
166 throwRsaDsa("RSA_public_encrypt");
167 }
168 else if((unsigned)irtn > cipherTextLen) {
169 rsaCryptDebug("RSA_public_encrypt overflow");
170 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
171 }
172 cipherTextLen = (size_t)irtn;
173 }
174
175 void RSA_CryptContext::decryptBlock(
176 const void *cipherText, // length implied (one cipher block)
177 size_t cipherTextLen,
178 void *plainText,
179 size_t &plainTextLen, // in/out, throws on overflow
180 bool final)
181 {
182 StLock<Mutex> _(gMutex());
183
184 int irtn;
185
186 rsaCryptDebug("decryptBlock padding %d", mPadding);
187 /* FIXME do OAEP encoding here */
188 if(mRsaKey->d == NULL) {
189 irtn = RSA_public_decrypt((int)inBlockSize(),
190 (unsigned char *)cipherText,
191 (unsigned char *)plainText,
192 mRsaKey,
193 mPadding);
194 }
195 else {
196 irtn = RSA_private_decrypt((int)inBlockSize(),
197 (unsigned char *)cipherText,
198 (unsigned char *)plainText,
199 mRsaKey,
200 mPadding);
201 }
202 if(irtn < 0) {
203 rsaCryptDebug("decryptBlock err");
204 throwRsaDsa("RSA_private_decrypt");
205 }
206 else if((unsigned)irtn > plainTextLen) {
207 rsaCryptDebug("RSA_private_decrypt overflow");
208 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
209 }
210 plainTextLen = (size_t)irtn;
211 }
212
213 size_t RSA_CryptContext::outputSize(
214 bool final, // ignored
215 size_t inSize /*= 0*/) // output for given input size
216 {
217 StLock<Mutex> _(gMutex());
218
219 size_t rawBytes = inSize + inBufSize();
220 size_t rawBlocks = (rawBytes + inBlockSize() - 1) / inBlockSize();
221 rbprintf("--- RSA_CryptContext::outputSize inSize 0x%lux outSize 0x%lux mInBufSize 0x%lux",
222 (unsigned long)inSize, (unsigned long)(rawBlocks * outBlockSize()), (unsigned long)inBufSize());
223 return rawBlocks * outBlockSize();
224 }