]> git.saurik.com Git - apple/security.git/blob - AppleCSP/RSA_DSA/RSA_asymmetric.cpp
Security-30.1.tar.gz
[apple/security.git] / AppleCSP / RSA_DSA / RSA_asymmetric.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 * RSA_asymmetric.cpp - CSPContext for RSA asymmetric encryption
21 */
22
23 #include "RSA_asymmetric.h"
24 #include "RSA_DSA_utils.h"
25 #include <Security/debugging.h>
26
27 #define rsaCryptDebug(args...) debug("rsaCrypt", ## args)
28 #define rbprintf(args...) debug("rsaBuf", ## args)
29
30 RSA_CryptContext::~RSA_CryptContext()
31 {
32 if(mAllocdRsaKey) {
33 assert(mRsaKey != NULL);
34 RSA_free(mRsaKey);
35 mRsaKey = NULL;
36 mAllocdRsaKey = false;
37 }
38 }
39
40 /* called by CSPFullPluginSession */
41 void RSA_CryptContext::init(const Context &context, bool encoding = true)
42 {
43 if(mInitFlag && !opStarted()) {
44 /* reusing - e.g. query followed by encrypt */
45 return;
46 }
47
48 /* optional mode to use alternate key class (e.g., decrypt with public key) */
49 CSSM_KEYCLASS keyClass;
50 switch (context.getInt(CSSM_ATTRIBUTE_MODE)) {
51 case CSSM_ALGMODE_PUBLIC_KEY:
52 keyClass = CSSM_KEYCLASS_PUBLIC_KEY;
53 break;
54 case CSSM_ALGMODE_PRIVATE_KEY:
55 keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
56 break;
57 case CSSM_ALGMODE_NONE:
58 /* default, not present in context: infer from op type */
59 keyClass = encoding ? CSSM_KEYCLASS_PUBLIC_KEY : CSSM_KEYCLASS_PRIVATE_KEY;
60 break;
61 default:
62 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE);
63 }
64
65 /* fetch key from context */
66 if(mRsaKey == NULL) {
67 assert(!opStarted());
68 mRsaKey = contextToRsaKey(context,
69 session(),
70 keyClass,
71 encoding ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
72 mAllocdRsaKey);
73 }
74 else {
75 assert(opStarted());
76 }
77
78 /* validate context - TBD */
79
80 /* finally, have BlockCryptor set up its stuff. */
81 unsigned cipherBlockSize = RSA_size(mRsaKey);
82 unsigned plainBlockSize = cipherBlockSize - 11;
83 setup(encoding ? plainBlockSize : cipherBlockSize, // blockSizeIn
84 encoding ? cipherBlockSize : plainBlockSize, // blockSizeOut
85 false, // pkcs5Pad
86 false, // needsFinal
87 BCM_ECB,
88 NULL); // IV
89 mInitFlag = true;
90
91 }
92 /* called by BlockCryptor */
93 void RSA_CryptContext::encryptBlock(
94 const void *plainText, // length implied (one block)
95 size_t plainTextLen,
96 void *cipherText,
97 size_t &cipherTextLen, // in/out, throws on overflow
98 bool final)
99 {
100 int irtn;
101
102 if(mRsaKey->d == NULL) {
103 irtn = RSA_public_encrypt(plainTextLen,
104 (unsigned char *)plainText,
105 (unsigned char *)cipherText,
106 mRsaKey,
107 RSA_PKCS1_PADDING);
108 }
109 else {
110 irtn = RSA_private_encrypt(plainTextLen,
111 (unsigned char *)plainText,
112 (unsigned char *)cipherText,
113 mRsaKey,
114 RSA_PKCS1_PADDING);
115 }
116 if(irtn < 0) {
117 throwRsaDsa("RSA_public_encrypt");
118 }
119 else if((unsigned)irtn > cipherTextLen) {
120 rsaCryptDebug("RSA_public_encrypt overflow");
121 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
122 }
123 cipherTextLen = (size_t)irtn;
124 }
125
126 void RSA_CryptContext::decryptBlock(
127 const void *cipherText, // length implied (one cipher block)
128 void *plainText,
129 size_t &plainTextLen, // in/out, throws on overflow
130 bool final)
131 {
132 int irtn;
133
134 if(mRsaKey->d == NULL) {
135 irtn = RSA_public_decrypt(inBlockSize(),
136 (unsigned char *)cipherText,
137 (unsigned char *)plainText,
138 mRsaKey,
139 RSA_PKCS1_PADDING);
140 }
141 else {
142 irtn = RSA_private_decrypt(inBlockSize(),
143 (unsigned char *)cipherText,
144 (unsigned char *)plainText,
145 mRsaKey,
146 RSA_PKCS1_PADDING);
147 }
148 if(irtn < 0) {
149 throwRsaDsa("RSA_private_decrypt");
150 }
151 else if((unsigned)irtn > plainTextLen) {
152 rsaCryptDebug("RSA_private_decrypt overflow");
153 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
154 }
155 plainTextLen = (size_t)irtn;
156 }
157
158 size_t RSA_CryptContext::outputSize(
159 bool final, // ignored
160 size_t inSize = 0) // output for given input size
161 {
162 UInt32 rawBytes = inSize + inBufSize();
163 UInt32 rawBlocks = (rawBytes + inBlockSize() - 1) / inBlockSize();
164 rbprintf("--- RSA_CryptContext::outputSize inSize 0x%lx outSize 0x%lx mInBufSize 0x%lx",
165 inSize, rawBlocks * outBlockSize(), inBufSize());
166 return rawBlocks * outBlockSize();
167 }