1 /* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved.
3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE,
7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
8 * EXPOSE YOU TO LIABILITY.
9 ***************************************************************************
11 * NSFEEPublicKey.m - NSFEEPublicKey class implementation
16 * Added ECDSA signature routines.
18 * Modified to use C-only FeePublicKey module.
19 * ???? 1994 Blaine Garst at NeXT
23 #import <Foundation/Foundation.h>
24 #import <Foundation/NSUtilities.h>
26 #import "NSCryptors.h"
27 #import "NSFEEPublicKeyPrivate.h"
28 #import "feePublicKey.h"
29 #import "feePublicKeyPrivate.h"
30 #import "ckutilities.h"
33 #import "curveParams.h"
35 #import "feeDigitalSignature.h"
37 #import "feeFunctions.h"
38 #import "feeFEEDExp.h"
41 Elliptic curve algebra over finite fields F(p**k), where p = 2**q -1 is a
44 A private key (a) is a large integer that when multiplied by an initial
45 curve point P yields the public key aP.
46 Public keys can be used to generate one-time pads because multiplication
52 @implementation NSFEEPublicKey
55 * Root method to create new public key from private "password" data.
57 + keyWithPrivateData:(NSData *)passwd
59 usageName:(NSString *)uname
61 NSFEEPublicKey *result;
65 result = [[self alloc] autorelease];
66 result->_pubKey = feePubKeyAlloc();
67 uc = fmalloc([uname length] * sizeof(unichar));
68 [uname getCharacters:uc];
69 frtn = feePubKeyInitFromPrivData(result->_pubKey,
70 [passwd bytes], [passwd length],
75 NSLog(@"keyWithPrivateData: %s\n", feeReturnString(frtn));
82 * Create new key with curve parameters matching existing oldKey.
84 + keyWithPrivateData:(NSData *)passwd
85 andKey:(NSFEEPublicKey *)oldKey
86 usageName:(NSString *)uname
88 NSFEEPublicKey *result;
92 result = [[self alloc] autorelease];
93 result->_pubKey = feePubKeyAlloc();
94 uc = fmalloc([uname length] * sizeof(unichar));
95 [uname getCharacters:uc];
96 frtn = feePubKeyInitFromKey(result->_pubKey,
97 [passwd bytes], [passwd length],
102 NSLog(@"keyWithPrivateData:andKey: %s\n",
103 feeReturnString(frtn));
109 + keyWithPrivateData:(NSData *)passwd
110 usageName:(NSString *)uname
112 // 4 gives 127 bits of protection
113 // although the RSA challenge number of 127 bits has been
114 // broken, FEE is much stronger at the same length
115 return [self keyWithPrivateData:passwd
116 depth:FEE_DEPTH_DEFAULT
121 * The standard way of creating a new key given a private "password" string.
123 + keyWithPrivateString:(NSString *)private
124 usageName:(NSString *)uname
130 * FIXME - handle other encodings?
132 pdata = [private dataUsingEncoding:NSUTF8StringEncoding];
133 result = [self keyWithPrivateData:pdata usageName:uname];
137 + keyWithPrivateString:(NSString *)private
138 andKey:(NSFEEPublicKey *)oldKey
139 usageName:(NSString *)uname
144 if (!uname) return nil;
146 pdata = [private dataUsingEncoding:NSUTF8StringEncoding];
147 result = [self keyWithPrivateData:pdata andKey:oldKey usageName:uname];
151 + keyWithPrivateString:(NSString *)private
152 depth:(unsigned)depth
153 usageName:(NSString *)uname
158 if (!uname) return nil;
160 pdata = [private dataUsingEncoding:NSUTF8StringEncoding];
161 result = [self keyWithPrivateData:pdata depth:depth usageName:uname];
166 * The standard way of creating a new key given a public key string.
168 + keyWithPublicKeyString:(NSString *)hexstr
170 NSFEEPublicKey *result;
172 NSStringEncoding defEndoding;
176 * Protect against gross errors in the key string formatting...
178 defEndoding = [NSString defaultCStringEncoding];
179 if([hexstr canBeConvertedToEncoding:defEndoding] == NO) {
180 NSLog(@"NSFEEPublicKey: Bad Public Key String Format (1)\n");
185 * FIXME - docs say this string is "autoreleased". How is a cString
188 s = [hexstr cString];
189 result = [[self alloc] autorelease];
190 result->_pubKey = feePubKeyAlloc();
192 frtn = feePubKeyInitFromKeyString(result->_pubKey,
195 NSLog(@"keyWithPublicKeyString:andKey: %s\n",
196 feeReturnString(frtn));
205 feePubKeyFree(_pubKey);
211 * Create a public key in the form of a string. This string contains an
212 * encoded version of all of our ivars except for _private.
214 * See KeyStringFormat.doc for info on the format of the public key string;
215 * PLEASE UPDATE THIS DOCUMENT WHEN YOU MAKE CHANGES TO THE STRING FORMAT.
217 - (NSString *)publicKeyString
224 if(_pubKey == NULL) {
227 frtn = feePubKeyCreateKeyString(_pubKey, &keyStr, &keyStrLen);
229 NSLog(@"publicKeyString: %s\n",
230 feeReturnString(frtn));
233 result = [NSString stringWithCString:keyStr];
234 ffree((void *)keyStr);
238 - (BOOL)isEqual:(NSFEEPublicKey *)other
240 if((other == nil) || (other->_pubKey == NULL) || (_pubKey == NULL)) {
243 if(feePubKeyIsEqual(_pubKey, other->_pubKey)) {
251 - (unsigned)keyBitsize
253 if(_pubKey == NULL) {
256 return feePubKeyBitsize(_pubKey);
259 - (NSString *)algorithmName
261 return [NSString stringWithCString:feePubKeyAlgorithmName()];
264 - (NSString *)usageName
267 const feeUnichar *uname;
270 if(_pubKey == NULL) {
273 uname = feePubKeyUsageName(_pubKey, &unameLen);
274 result = [NSString stringWithCharacters:uname length:unameLen];
280 return [self usageName];
283 - (NSData *)padWithPublicKey:(id <NSObject,NSPublicKey>)otherKey
285 NSFEEPublicKey *other;
286 NSMutableData *result;
288 unsigned char *padData;
291 if(_pubKey == NULL) {
294 if (![otherKey isMemberOfClass:isa]) {
298 if(other->_pubKey == NULL) {
301 frtn = feePubKeyCreatePad(_pubKey,
306 NSLog(@"padWithPublicKey: %s\n", feeReturnString(frtn));
309 result = [NSData dataWithBytesNoCopy:padData length:padDataLen];
313 - (NSData *)encryptData:(NSData *)data
318 unsigned char *ctext;
321 if(_pubKey == NULL) {
324 feed = feeFEEDExpNewWithPubKey(_pubKey);
325 frtn = feeFEEDExpEncrypt(feed,
330 if(frtn == FR_Success) {
331 result = [NSData dataWithBytesNoCopy:ctext length:ctextLen];
334 NSLog(@"feeFEEDEncrypt: %s\n", feeReturnString(frtn));
337 feeFEEDExpFree(feed);
341 - (NSData *)decryptData:(NSData *)data
346 unsigned char *ptext;
349 if(_pubKey == NULL) {
352 feed = feeFEEDExpNewWithPubKey(_pubKey);
353 frtn = feeFEEDExpDecrypt(feed,
358 if(frtn == FR_Success) {
359 result = [NSData dataWithBytesNoCopy:ptext length:ptextLen];
362 NSLog(@"feeFEEDDecrypt: %s\n", feeReturnString(frtn));
365 feeFEEDExpFree(feed);
370 * When 1, we use ECDSA unless we're using a depth which does not
372 * WARNING - enabling ECDSA by default breaks ICE and compatibility
373 * with Java signatures, at least until we have a Java ECDSA
376 #define ECDSA_SIG_DEFAULT 0
378 - (NSData *)digitalSignatureForData:(NSData *)data
386 if(_pubKey == NULL) {
389 cp = feePubKeyCurveParams(_pubKey);
390 if(!ECDSA_SIG_DEFAULT || isZero(cp->x1OrderPlus)) {
391 frtn = feePubKeyCreateSignature(_pubKey,
398 frtn = feePubKeyCreateECDSASignature(_pubKey,
405 NSLog(@"digitalSignatureForData: %s\n", feeReturnString(frtn));
408 result = [NSData dataWithBytesNoCopy:sig length:sigLen];
412 - (BOOL)isValidDigitalSignature:(NSData *)signa
413 forData:(NSData *)data
416 feeUnichar *sigSigner;
417 unsigned sigSignerLen;
420 if(_pubKey == NULL) {
423 cp = feePubKeyCurveParams(_pubKey);
424 if(!ECDSA_SIG_DEFAULT || isZero(cp->x1OrderPlus)) {
425 frtn = feePubKeyVerifySignature(_pubKey,
434 frtn = feePubKeyVerifyECDSASignature(_pubKey,
444 * FIXME - We just throw away the signer for now...
453 case FR_InvalidSignature:
457 * Something other than simple signature mismatch...
459 NSLog(@"isValidDigitalSignature: %s\n", feeReturnString(frtn));
466 @implementation NSFEEPublicKey(Private)
470 if(_pubKey == NULL) {
473 return feePubKeyMinusCurve(_pubKey);
478 if(_pubKey == NULL) {
481 return feePubKeyPlusCurve(_pubKey);
484 - (feePubKey)feePubKey
492 printPubKey(_pubKey);