- goto failEC;
- }
- requiredPublicHeader = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, headerBytes, headerLen, kCFAllocatorNull);
- if (!requiredPublicHeader) {
- secdebug("key", "SecKeyCopyPublicBytes: requiredPublicHeader is nil (1)");
- goto failEC;
- }
- publicDataHeader = _CFDataCreateReferenceFromRange(kCFAllocatorDefault,
- tempPublicData, CFRangeMake(0, headerLen));
- if (!publicDataHeader) {
- secdebug("key", "SecKeyCopyPublicBytes: publicDataHeader is nil (1)");
- goto failEC;
- }
- headerlessPublicData = _CFDataCreateCopyFromRange(kCFAllocatorDefault,
- tempPublicData, CFRangeMake(headerLen, CFDataGetLength(tempPublicData) - headerLen));
- if (!headerlessPublicData) {
- secdebug("key", "SecKeyCopyPublicBytes: headerlessPublicData is nil (1)");
- goto failEC;
- }
- if(!_CFDataEquals(publicDataHeader, requiredPublicHeader)) {
- CFRelease(publicDataHeader);
- CFRelease(headerlessPublicData);
- CFRelease(requiredPublicHeader);
- requiredPublicHeader = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, altHdrBytes, altHdrLen, kCFAllocatorNull);
- if (!requiredPublicHeader) {
- secdebug("key", "SecKeyCopyPublicBytes: requiredPublicHeader is nil (2)");
- goto failEC;
- }
- publicDataHeader = _CFDataCreateReferenceFromRange(kCFAllocatorDefault,
- tempPublicData, CFRangeMake(0, altHdrLen));
- if (!publicDataHeader) {
- secdebug("key", "SecKeyCopyPublicBytes: publicDataHeader is nil (2)");
- goto failEC;
- }
- headerlessPublicData = _CFDataCreateCopyFromRange(kCFAllocatorDefault,
- tempPublicData, CFRangeMake(altHdrLen, CFDataGetLength(tempPublicData) - altHdrLen));
- if (!headerlessPublicData) {
- secdebug("key", "SecKeyCopyPublicBytes: headerlessPublicData is nil (2)");
- goto failEC;
- }
- }
- if(!_CFDataEquals(publicDataHeader, requiredPublicHeader)) {
- #if ECDSA_DEBUG
- CFIndex dataLen = CFDataGetLength(tempPublicData);
- const UInt8 *dataPtr = CFDataGetBytePtr(tempPublicData);
- syslog(LOG_NOTICE, "Public key data (with header):");
- secdump((const unsigned char *)dataPtr,(unsigned long)dataLen);
- dataLen = CFDataGetLength(requiredPublicHeader);
- dataPtr = CFDataGetBytePtr(requiredPublicHeader);
- syslog(LOG_NOTICE, "Required header:");
- secdump((const unsigned char *)dataPtr,(unsigned long)dataLen);
- dataLen = CFDataGetLength(publicDataHeader);
- dataPtr = CFDataGetBytePtr(publicDataHeader);
- syslog(LOG_NOTICE, "Actual header:");
- secdump((const unsigned char *)dataPtr,(unsigned long)dataLen);
- #endif
- secdebug("key", "_SecKeyCopyPublicBytes: public data header mismatch");
- goto failEC;
- }
- if(publicBytes) {
- *publicBytes = headerlessPublicData;
- ecStatus = errSecSuccess;
+
+ return ecStatus;
+ }
+
+
+ // Get a pointer to the first byte of the exported data
+ pData_Ptr = CFDataGetBytePtr(tempPublicData);
+
+ // the first byte should be a sequence 0x30
+ if (*pData_Ptr != 0x30)
+ {
+ secdebug("key", "SecKeyCopyPublicBytes: exported data is invalid");
+ if (NULL != tempPublicData)
+ CFRelease(tempPublicData);
+
+ ecStatus = errSecParam;
+ return ecStatus;
+ }
+
+ // move past the sequence byte
+ pData_Ptr++;
+
+ // Check to see if the high bit is set which
+ // indicates that the length will be at least
+ // two bytes. If the high bit is set then
+ // The lower seven bits specifies the number of
+ // bytes used for the length. The additonal 1
+ // is for the current byte. Otherwise just move past the
+ // single length byte
+ pData_Ptr += (*pData_Ptr & 0x80) ? ((*pData_Ptr & 0x7F) + 1) : 1;
+
+ // The current byte should be a sequence 0x30
+ if (*pData_Ptr != 0x30)
+ {
+ secdebug("key", "SecKeyCopyPublicBytes: Could not find the key sequence");
+ if (NULL != tempPublicData)
+ CFRelease(tempPublicData);
+
+ ecStatus = errSecParam;
+
+ return ecStatus;
+ }
+
+ // The next bytes will always be the same
+ // 0x30 = SEQUENCE
+ // XX Length Byte
+ // 0x06 OBJECT ID
+ // 0x07 Length Byte
+ // ECDSA public KEY OID value 0x2a,0x86,0x48,0xce,0x3d,0x02,0x01
+ // 0x06 OBJECT ID
+ // This is a total of 12 bytes
+ pData_Ptr += 12;
+
+ // Next byte is the length of the ECDSA curve OID
+ // Move past the length byte and the curve OID
+ pData_Ptr += (((int)*pData_Ptr) + 1);
+
+ // Should be at a BINARY String which is specifed by a 0x3
+ if (*pData_Ptr != 0x03)
+ {
+ secdebug("key", "SecKeyCopyPublicBytes: Invalid key structure");
+ if (NULL != tempPublicData)
+ CFRelease(tempPublicData);
+
+ ecStatus = errSecParam;
+
+ return ecStatus;
+ }
+
+ // Move past the BINARY String specifier 0x03
+ pData_Ptr++;
+
+
+ // Check to see if the high bit is set which
+ // indicates that the length will be at least
+ // two bytes. If the high bit is set then
+ // The lower seven bits specifies the number of
+ // bytes used for the length. The additonal 1
+ // is for the current byte. Otherwise just move past the
+ // single length byte
+ pData_Ptr += (*pData_Ptr & 0x80) ? ((*pData_Ptr & 0x7F) + 1) : 1;
+
+ // Move past the beginning marker for the BINARY String 0x00
+ pData_Ptr++;
+
+ // pData_Ptr now points to the first bytes of the key material
+ headerLength = (CFIndex)(((intptr_t)pData_Ptr) - ((intptr_t)CFDataGetBytePtr(tempPublicData)));
+
+ headerlessPublicData = _CFDataCreateCopyFromRange(kCFAllocatorDefault,
+ tempPublicData, CFRangeMake(headerLength, CFDataGetLength(tempPublicData) - headerLength));
+
+ if (!headerlessPublicData)
+ {
+ printf("SecKeyCopyPublicBytes: headerlessPublicData is nil (1)\n");
+ if (NULL != tempPublicData)
+ CFRelease(tempPublicData);
+
+ ecStatus = errSecParam;
+
+ return ecStatus;