コード例 #1
0
ファイル: cert_data.c プロジェクト: xnuxer/vpnconnect
CertDataRef createCertDataFromCertificate(SecCertificateRef certificate)
{
  CertDataRef pCertData = (CertDataRef)malloc(sizeof(CertData));
  pCertData->subject = GetFieldsFromCertificate(certificate, kSecOIDX509V1SubjectName);
  pCertData->issuer = GetFieldsFromCertificate(certificate, kSecOIDX509V1IssuerName);

  CFDataRef data = SecCertificateCopyData(certificate);
  if (data == NULL)
    {
      warnx("SecCertificateCopyData() returned NULL");
      destroyCertData(pCertData);
      return NULL;
    }

  unsigned char sha1[CC_SHA1_DIGEST_LENGTH];
  CC_SHA1(CFDataGetBytePtr(data), CFDataGetLength(data), sha1);
  pCertData->sha1 = createHexString(sha1, CC_SHA1_DIGEST_LENGTH);

  unsigned char md5[CC_MD5_DIGEST_LENGTH];
  CC_MD5(CFDataGetBytePtr(data), CFDataGetLength(data), md5);
  pCertData->md5 = createHexString((unsigned char*)md5, CC_MD5_DIGEST_LENGTH);

  CFDataRef serial = SecCertificateCopySerialNumber(certificate, NULL);
  pCertData->serial = createHexString((unsigned char *)CFDataGetBytePtr(serial), CFDataGetLength(serial));
  CFRelease(serial);

  return pCertData;
}
コード例 #2
0
void SHA1(sLONG_PTR *pResult, PackagePtr pParams)
{
	C_BLOB Param1;
	C_LONGINT Param2;
	C_TEXT returnValue;
	
	Param1.fromParamAtIndex(pParams, 1);
	Param2.fromParamAtIndex(pParams, 2);
	
	uint8_t *buf = (uint8_t *)calloc(20, sizeof(uint8_t)); 
	
	CC_SHA1((unsigned char *)Param1.getBytesPtr(), Param1.getBytesLength(), buf);	
	
	C_BLOB temp;
	temp.setBytes((const uint8_t *)buf, 20);
	
	switch (Param2.getIntValue()) 
	{
		case 1:
			temp.toB64Text(&returnValue);	
			break;
		default:
			temp.toHexText(&returnValue);	
			break;
	}
	
	free(buf);
	
	returnValue.setReturn(pResult);
}
コード例 #3
0
ファイル: sha.c プロジェクト: BillTheBest/kaa
kaa_error_t ext_calculate_sha_hash(const char *data, size_t data_size, kaa_digest digest)
{
    KAA_RETURN_IF_NIL(digest, KAA_ERR_BADPARAM);

    CC_SHA1((const unsigned char *)data, data_size, digest);
    return KAA_ERR_NONE;
}
コード例 #4
0
bool
mongoc_crypto_common_crypto_sha1 (mongoc_crypto_t     *crypto,
                                  const unsigned char *input,
                                  const size_t         input_len,
                                  unsigned char       *output /* OUT */)
{
   return CC_SHA1 (input, input_len, output);
}
コード例 #5
0
void RSASHA1(sLONG_PTR *pResult, PackagePtr pParams)
{
	C_BLOB Param1;
	C_BLOB Param2;
	C_LONGINT Param3;
	C_TEXT returnValue;
    
	Param1.fromParamAtIndex(pParams, 1);
	Param2.fromParamAtIndex(pParams, 2);
	Param3.fromParamAtIndex(pParams, 3);
	
	uint8_t *buf = (uint8_t *)calloc(20, sizeof(uint8_t)); 
	
	CC_SHA1((unsigned char *)Param1.getBytesPtr(), Param1.getBytesLength(), buf);	    
    
    unsigned int signatureLength = 0;
    
	BIO *bio = BIO_new_mem_buf((void *)Param2.getBytesPtr(), Param2.getBytesLength());
	
	if(bio){
		
		RSA *key = NULL;
		key = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);	
		
		if(key){
			
			uint8_t *sgn = (uint8_t *)calloc(RSA_size(key), sizeof(uint8_t)); 
			
			if(RSA_sign(NID_sha1, buf, 20, sgn, &signatureLength, key)){
				
				C_BLOB temp;
				temp.setBytes((const uint8_t *)sgn, signatureLength);
				
				switch (Param3.getIntValue()) 
				{
					case 1:
						temp.toB64Text(&returnValue);	
						break;
					default:
						temp.toHexText(&returnValue);	
						break;
				}
			}
			
			free(sgn);
		}
		
		BIO_free(bio);
	}
    
	free(buf);
	
	returnValue.setReturn(pResult);
}
コード例 #6
0
int p12_pbe_gen(CFStringRef passphrase, uint8_t *salt_ptr, size_t salt_length, 
    unsigned iter_count, P12_PBE_ID pbe_id, uint8_t *data, size_t length)
{
    unsigned int hash_blocksize = CC_SHA1_BLOCK_BYTES;
    unsigned int hash_outputsize = CC_SHA1_DIGEST_LENGTH;

    if (!passphrase)
        return -1;

    /* generate diversifier block */
    unsigned char diversifier[hash_blocksize];    
    memset(diversifier, pbe_id, sizeof(diversifier));

    /* convert passphrase to BE UTF16 and append double null */
    CFDataRef passphrase_be_unicode = CFStringCreateExternalRepresentation(kCFAllocatorDefault, passphrase, kCFStringEncodingUTF16BE, '\0');
    if (!passphrase_be_unicode)
        return -1;
    uint8_t null_termination[2] = { 0, 0 };
    CFMutableDataRef passphrase_be_unicode_null_term = CFDataCreateMutableCopy(NULL, 0, passphrase_be_unicode);
    CFRelease(passphrase_be_unicode);
    if (!passphrase_be_unicode_null_term)
        return -1;
    CFDataAppendBytes(passphrase_be_unicode_null_term, null_termination, sizeof(null_termination));

    /* generate passphrase block */
    uint8_t *passphrase_data = NULL;
    size_t passphrase_data_len = 0;
    size_t passphrase_length = CFDataGetLength(passphrase_be_unicode_null_term);
    const unsigned char *passphrase_ptr = CFDataGetBytePtr(passphrase_be_unicode_null_term);
    passphrase_data = concatenate_to_blocksize(passphrase_ptr, passphrase_length, hash_blocksize, &passphrase_data_len);
    CFRelease(passphrase_be_unicode_null_term);
    if (!passphrase_data)
        return -1;

    /* generate salt block */
    uint8_t *salt_data = NULL;
    size_t salt_data_len = 0;
    if (salt_length)
        salt_data = concatenate_to_blocksize(salt_ptr, salt_length, hash_blocksize, &salt_data_len);
    if (!salt_data)
        return -1;
    
    /* generate S||P block */
    size_t I_length = salt_data_len + passphrase_data_len;
    uint8_t *I_data = malloc(I_length);
    if (!I_data)
        return -1;
        
    memcpy(I_data + 0, salt_data, salt_data_len);
    memcpy(I_data + salt_data_len, passphrase_data, passphrase_data_len);
    free(salt_data);
    free(passphrase_data);

    /* round up output buffer to multiple of hash block size and allocate */
    size_t hash_output_blocks = (length + hash_outputsize - 1) / hash_outputsize;
    size_t temp_buf_size = hash_output_blocks * hash_outputsize;
    uint8_t *temp_buf = malloc(temp_buf_size);
    uint8_t *cursor = temp_buf;
    if (!temp_buf)
        return -1;

    /* 64 bits cast(s): worst case here is we dont hash all the data and incorectly derive the wrong key,
       when the passphrase + salt are over 2^32 bytes long */
    /* loop over output in hash_output_size increments */
    while (cursor < temp_buf + temp_buf_size) {
        CC_SHA1_CTX ctx;
        CC_SHA1_Init(&ctx);
        CC_SHA1_Update(&ctx, diversifier, (CC_LONG)sizeof(diversifier));
        assert(I_length<=UINT32_MAX); /* debug check. Correct as long as CC_LONG is uint32_t */
        CC_SHA1_Update(&ctx, I_data, (CC_LONG)I_length);
        CC_SHA1_Final(cursor, &ctx);

        /* run block through SHA-1 for iteration count */
        unsigned int i;
        for (i = 1; /*first round done above*/ i < iter_count; i++)
            CC_SHA1(cursor, hash_outputsize, cursor);

        /*
         * b) Concatenate copies of A[i] to create a string B of 
         *    length v bits (the final copy of A[i]i may be truncated 
         *    to create B).
         */
        size_t A_i_len = 0;
        uint8_t *A_i = concatenate_to_blocksize(cursor, 
            hash_outputsize, hash_blocksize, &A_i_len);
        if (!A_i)
            return -1;
        
        /*
         * c) Treating I as a concatenation I[0], I[1], ..., 
         *    I[k-1] of v-bit blocks, where k = ceil(s/v) + ceil(p/v),
         *    modify I by setting I[j]=(I[j]+B+1) mod (2 ** v)
         *    for each j.
         */

        /* tmp1 = B+1 */

        const cc_size tmp_n = ccn_nof_size(A_i_len + 1) > ccn_nof_size(hash_blocksize) ? ccn_nof_size(A_i_len + 1) : ccn_nof_size(hash_blocksize);
        cc_unit tmp1[tmp_n];
        ccn_read_uint(tmp_n, tmp1, A_i_len, A_i);
        ccn_add1(tmp_n, tmp1, tmp1, 1);

        free(A_i);

        cc_unit tmp2[tmp_n];
        unsigned int j;
        for (j = 0; j < I_length; j+=hash_blocksize) {
            /* tempg = I[j];  */
            ccn_read_uint(tmp_n, tmp2, hash_blocksize, I_data + j);
            /* tempg += tmp1 */
            ccn_add(tmp_n, tmp2, tmp2, tmp1);
            
            /* I[j] = tempg mod 2**v
               Just clear all the high bits above 2**v
               In practice at most it rolled over by 1 bit, since all we did was add so
               we should only clear one bit at most.
             */
            size_t bitSize;
            const size_t hash_blocksize_bits = hash_blocksize * 8;
            while ((bitSize = ccn_bitlen(tmp_n, tmp2)) > hash_blocksize_bits)
            {
                ccn_set_bit(tmp2, bitSize - 1, 0);
            }

            ccn_write_uint_padded(tmp_n, tmp2, hash_blocksize, I_data + j);
        }

        cursor += hash_outputsize;
    }

    /*
     * 7. Concatenate A[1], A[2], ..., A[c] together to form a 
     *    pseudo-random bit string, A.
     *
     * 8. Use the first n bits of A as the output of this entire 
     *    process.
     */
    memmove(data, temp_buf, length);
    free(temp_buf);
    free(I_data);
    return 0;
}
コード例 #7
0
ファイル: sha1.c プロジェクト: RikuLindholm/adhd
void sha1(unsigned char *source, unsigned int len, unsigned char *target) {
    CC_SHA1(source, len, target);
}
コード例 #8
0
static bool
_mongoc_scram_generate_client_proof (mongoc_scram_t *scram,
                                     uint8_t        *outbuf,
                                     size_t          outbufmax,
                                     size_t         *outbuflen)
{
   /* ClientKey := HMAC(saltedPassword, "Client Key") */
   uint8_t client_key[MONGOC_SCRAM_HASH_SIZE];
   uint8_t stored_key[MONGOC_SCRAM_HASH_SIZE];
   uint8_t client_signature[MONGOC_SCRAM_HASH_SIZE];
   unsigned char client_proof[MONGOC_SCRAM_HASH_SIZE];
#if !defined(__APPLE__)
   uint32_t hash_len = 0;
#endif
   int i;
   int r = 0;

#if defined(__APPLE__)
   CCHmac (kCCHmacAlgSHA1,
           scram->salted_password,
           MONGOC_SCRAM_HASH_SIZE,
           (uint8_t *)MONGOC_SCRAM_CLIENT_KEY,
           strlen (MONGOC_SCRAM_CLIENT_KEY),
           client_key);
    
   /* StoredKey := H(client_key) */
   CC_SHA1 (client_key, MONGOC_SCRAM_HASH_SIZE, stored_key);

   /* ClientSignature := HMAC(StoredKey, AuthMessage) */
   CCHmac (kCCHmacAlgSHA1,
           stored_key,
           MONGOC_SCRAM_HASH_SIZE,
           scram->auth_message,
           scram->auth_messagelen,
           client_signature);
#else
   HMAC (EVP_sha1 (),
         scram->salted_password,
         MONGOC_SCRAM_HASH_SIZE,
         (uint8_t *)MONGOC_SCRAM_CLIENT_KEY,
         strlen (MONGOC_SCRAM_CLIENT_KEY),
         client_key,
         &hash_len);

   /* StoredKey := H(client_key) */
   SHA1 (client_key, MONGOC_SCRAM_HASH_SIZE, stored_key);

   /* ClientSignature := HMAC(StoredKey, AuthMessage) */
   HMAC (EVP_sha1 (),
         stored_key,
         MONGOC_SCRAM_HASH_SIZE,
         scram->auth_message,
         scram->auth_messagelen,
         client_signature,
         &hash_len);
#endif

   /* ClientProof := ClientKey XOR ClientSignature */

   for (i = 0; i < MONGOC_SCRAM_HASH_SIZE; i++) {
      client_proof[i] = client_key[i] ^ client_signature[i];
   }

   r = mongoc_b64_ntop (client_proof, sizeof (client_proof),
                        (char *)outbuf + *outbuflen,
                        outbufmax - *outbuflen);

   if (-1 == r) {
      return false;
   }

   *outbuflen += r;

   return true;
}
コード例 #9
0
ファイル: c4hash.c プロジェクト: rhardman/C4
C4Err HASH_DO(HASH_Algorithm algorithm, const unsigned char *in, unsigned long inlen, unsigned long outLen, uint8_t *out)
{
    
    C4Err             err         = kC4Err_NoErr;
    HASH_ContextRef     hashRef     = kInvalidHASH_ContextRef;
    uint8_t             hashBuf[128];
    uint8_t             *p = (outLen < sizeof(hashBuf))?hashBuf:out;
    
    
#if  _USES_COMMON_CRYPTO_
    
    /* use apple algorithms if possible*/
    switch(algorithm)
    {
        case kHASH_Algorithm_MD5:
            CC_MD5(in, (CC_LONG) inlen, hashBuf);
            goto complete;
            break;
            
        case  kHASH_Algorithm_SHA1:
            CC_SHA1(in, (CC_LONG) inlen, hashBuf);
            goto complete;
            break;
            
        case  kHASH_Algorithm_SHA224:
            CC_SHA224(in, (CC_LONG) inlen, hashBuf);
            goto complete;
            break;
            
        case  kHASH_Algorithm_SHA256:
            CC_SHA256(in, (CC_LONG) inlen, hashBuf);
            goto complete;
            break;
            
        case  kHASH_Algorithm_SHA384:
            CC_SHA384(in, (CC_LONG) inlen, hashBuf);
            goto complete;
            break;
            
        case  kHASH_Algorithm_SHA512:
            CC_SHA512(in, (CC_LONG) inlen, hashBuf);
            goto complete;
            break;
            
        default:
            break;
    }
    
#endif
    
    err = HASH_Init( algorithm, & hashRef); CKERR;
    err = HASH_Update( hashRef, in,  inlen); CKERR;
    err = HASH_Final( hashRef, p); CKERR;
    
complete:
    if((err == kC4Err_NoErr) & (p!= out))
        COPY(hashBuf, out, outLen);
    
done:
    if(!IsNull(hashRef))
        HASH_Free(hashRef);
    
    return err;
}
コード例 #10
0
ファイル: stkeys.c プロジェクト: xant/istkey
int
compute_key(char *strId, int year, char *output, int len) {

    unsigned char sha1_digest[40]={0};
    char ssid[8]={0},buf[8]={0},week,x1,x2,x3;
    int keys = 0,ssidLen = 0;
    int offset = 0;
    if(!(ssidLen = str2ssid(ssid,strId)))
        return -99;
    
    //fprintf(stdout,"\nGenerating keys..please wait\n\n");

    serial[3] = year | '0';

    // 52 weeks of the year

    for(week = 1;week <= 52;week++) {

      serial[4] = (week / 10) + '0';
      serial[5] = (week % 10) + '0';

      for(x1 = 0;x1 < 36;x1++) {

        serial[6] = hexmsb(charTable[x1]);
        serial[7] = hexlsb(charTable[x1]);

        for(x2 = 0;x2 < 36;x2++) {

          serial[8] = hexmsb(charTable[x2]);
          serial[9] = hexlsb(charTable[x2]);

          for(x3 = 0;x3 < 36;x3++) {
            
            serial[10] = hexmsb(charTable[x3]);
            serial[11] = hexlsb(charTable[x3]);

            // hash serial number with sha-1
            CC_SHA1(serial, SERIAL_LENGTH, sha1_digest);
            // compare SSID octets with last number of bytes supplied

            if(memcmp(&sha1_digest[(20-ssidLen)],ssid,ssidLen) == 0) {
              // check if more keys will fit in the provided buffer
              if (keys >= len/(OUTPUT_KEY_SIZE))
                  goto __done;

              keys++;
              memcpy(buf,serial,6);
              sprintf(&output[offset], "[%s**%C%C%C]: ", buf, charTable[x1],charTable[x2],charTable[x3]);
              offset += OUTPUT_OVERHEAD;
              dump_key(&output[offset],sha1_digest);
              offset += DEFAULT_KEY_SIZE*2;
              strcat(&output[offset], "\n");
              output[++offset] = 0; // ensure to null-terminate the string
            }
          }
        }
      }
    }
__done:
    //fprintf(stdout,"\nFound %d potential keys.\n",keys);
    return keys;
}
コード例 #11
0
int mongo_write(const char *path, const char *buf, size_t size,
                off_t offset, struct fuse_file_info *fi)
{
    struct inode * e;
    int res;
    size_t reallen;
    int32_t realend = size, blk_offset = 0;
    const off_t write_end = size + offset;
    char * lock;
    bson doc, cond;
    mongo * conn = get_conn();
    uint8_t hash[20];
    time_t now = time(NULL);

    e = (struct inode*)fi->fh;
    if((res = get_cached_inode(path, e)) != 0)
        return res;

    if(e->mode & S_IFDIR)
        return -EISDIR;

    /* Uncomment this for incredibly slow length calculations.
    for(;realend >= 0 && buf[realend] == '\0'; realend--);
    realend++;
    for(blk_offset = 0; blk_offset < realend && buf[blk_offset] == 0; blk_offset++);
    blk_offset -= blk_offset > 0 ? 1 : 0;
    * The code below uses SSE4 instructions to find the first/last
    * zero bytes by doing 16-byte comparisons at a time. This should give
    * a ~16 speed boost on blocks with lots of zero bytes over the dumb
    * method above.
    */
    
    if(size >= 16) {
        __m128i zero = _mm_setzero_si128();
        lock = (char*)buf + size - 16;
        while(lock >= buf) {
            __m128i x = _mm_loadu_si128((__m128i*)lock);
            res = _mm_movemask_epi8(_mm_cmpeq_epi8(zero, x));
            if(res == 0xffff) {
                lock -= 16;
                continue;
            }
            realend = lock - buf + fls(res ^ 0xffff);
            break;
        }
        if(lock <= buf)
            realend = 0;

        lock = (char*)buf;
        while(lock - buf < realend) {
            __m128i x = _mm_loadu_si128((__m128i*)lock);
            res = _mm_movemask_epi8(_mm_cmpeq_epi8(zero, x));
            if(res == 0xffff) {
                lock += 16;
                continue;
            }
            blk_offset = lock - buf + ffs(res ^ 0xffff) - 1;
            break;
        }
    }

    reallen = realend - blk_offset;
    if(reallen == 0) {
        pthread_mutex_lock(&e->wr_lock);
        res = insert_empty(&e->wr_extent, offset, size);
        goto end;
    }

#ifdef __APPLE__
    CC_SHA1(buf, size, hash);
#else
    SHA1(buf, size, hash);
#endif

    bson_init(&cond);
    bson_append_binary(&cond, "_id", 0, (char*)hash, sizeof(hash));
    bson_finish(&cond);

    bson_init(&doc);
    bson_append_start_object(&doc, "$setOnInsert");
    char * comp_out = get_compress_buf();
    size_t comp_size = snappy_max_compressed_length(reallen);
    if((res = snappy_compress(buf + blk_offset, reallen,
        comp_out, &comp_size)) != SNAPPY_OK) {
        fprintf(stderr, "Error compressing input: %d\n", res);
        return -EIO;
    }
    bson_append_binary(&doc, "data", 0, comp_out, comp_size);
    bson_append_int(&doc, "offset", blk_offset);
    bson_append_int(&doc, "size", size);
    bson_append_time_t(&doc, "created", now);
    bson_append_finish_object(&doc);
    bson_finish(&doc);

    res = mongo_update(conn, blocks_name, &cond, &doc,
        MONGO_UPDATE_UPSERT, NULL);
    bson_destroy(&doc);
    bson_destroy(&cond);

    if(res != MONGO_OK) {
        fprintf(stderr, "Error committing block %s\n", conn->lasterrstr);
        return -EIO;
    }

    pthread_mutex_lock(&e->wr_lock);
    res = insert_hash(&e->wr_extent, offset, size, hash);

end:
    if(write_end > e->size)
        e->size = write_end;

    if(now - e->wr_age > 3) {
        res = serialize_extent(e, e->wr_extent);
        if(res != 0) {
            pthread_mutex_unlock(&e->wr_lock);
            return res;    
        }
        e->wr_age = now;
    }
    pthread_mutex_unlock(&e->wr_lock);
    if(res != 0)
        return res;

    res = update_filesize(e, write_end);

    if(res != 0)
        return res;
    return size;
}
コード例 #12
0
CFDataRef decrypt_data_ios3(const uint8_t* datab, uint32_t len, uint32_t* pclass)
{
    IOAESStruct in;
    IOReturn ret;
    unsigned char md[20];
    unsigned char pad;
    size_t IOAESStructSize = sizeof(IOAESStruct) - 4; //iOS 3 size

    if (pclass != NULL)
        *pclass = kSecAttrAccessibleAlways;

    if (len < 48) //iv + sha1 (20, rounded to 32) = 16 + 32
    {
        fprintf(stderr, "decrypt_data_ios3 : len < 48\n");
        return NULL;
    }
    len = len - 16;

    uint8_t* buffer = valloc(len);
    if (buffer == NULL)
    {
        return NULL;
    }
    uint8_t* output_buffer = valloc(len);
    if (output_buffer == NULL)
    {
        free(buffer);
        return NULL;
    }
    memcpy(buffer, &datab[16], len);

    in.mode = kIOAESAcceleratorDecrypt;
    in.bits = 128;
    in.cleartext = output_buffer;
    in.ciphertext = buffer;
    in.size = len;
    in.mask = kIOAESAccelerator835Mask;

    memset(in.keybuf, 0, sizeof(in.keybuf));

    memcpy(in.iv, datab, 16);

    io_service_t conn = IOKit_getConnect("IOAESAccelerator");

    uid_t saved_uid = geteuid();
    if(seteuid(64) == -1) //securityd
    {
        fprintf(stderr, "seteuid(_securityd) failed, errno=%d\n", errno);
    }
    if(geteuid() != 64) //HAX otherwise looks like the new uid isnt "commited"
    {
        fprintf(stderr,"geteuid=%x\n", geteuid());
    }
    ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize);

    if (ret == 0xe00002c2) //if we have an iOS 3 keychain on iOS 4
    {
        IOAESStructSize += 4;
        ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize);
    }
    if (seteuid(saved_uid) == -1)
    {
        fprintf(stderr, "seteuid(saved_uid) failed, errno=%d\n", errno);
    }

    if (ret != 0)
    {
        fprintf(stderr, "decrypt_data_ios3 : saved_uid=%d IOConnectCallStructMethod = %x\n", saved_uid, ret);
        free(buffer);
        free(output_buffer);
        return NULL;
    }
    pad = output_buffer[len - 1];
    if (pad > 16 || pad > len || pad == 0) {
        fprintf(stderr, "decrypt_data_ios3 : bad padding = %x\n", pad);
        free(buffer);
        free(output_buffer);
        return NULL;
    }
    len = len - 20 - pad;
    if (len & 0x80000000) {
        fprintf(stderr, "decrypt_data_ios3 : length underflow, should not happen len= %x\n", len);
        free(buffer);
        free(output_buffer);
        return NULL;
    }
    CC_SHA1(output_buffer, len, md);
    if (memcmp(&output_buffer[len], md, 20)) {
        fprintf(stderr, "decrypt_data_ios3 : SHA1 mismatch\n");
        free(buffer);
        free(output_buffer);
        return NULL;
    }
    CFDataRef data = CFDataCreate(kCFAllocatorDefault, output_buffer, len);
    free(buffer);
    free(output_buffer);

    return data;
}