/* generate KEYS -- as per PKCS12 section 7. * only used for MAC */ SECItem * sec_pkcs12_generate_key_from_password(SECOidTag algorithm, SECItem *salt, SECItem *password) { unsigned char *pre_hash = NULL; unsigned char *hash_dest = NULL; SECStatus res; PLArenaPool *poolp; SECItem *key = NULL; int key_len = 0; if ((salt == NULL) || (password == NULL)) { return NULL; } poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (poolp == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; } pre_hash = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(char) * (salt->len + password->len)); if (pre_hash == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } hash_dest = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(unsigned char) * SHA1_LENGTH); if (hash_dest == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } PORT_Memcpy(pre_hash, salt->data, salt->len); /* handle password of 0 length case */ if (password->len > 0) { PORT_Memcpy(&(pre_hash[salt->len]), password->data, password->len); } res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, pre_hash, (salt->len + password->len)); if (res == SECFailure) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } switch (algorithm) { case SEC_OID_SHA1: if (key_len == 0) key_len = 16; key = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); if (key == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * key_len); if (key->data == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } key->len = key_len; PORT_Memcpy(key->data, &hash_dest[SHA1_LENGTH - key->len], key->len); break; default: goto loser; break; } PORT_FreeArena(poolp, PR_TRUE); return key; loser: PORT_FreeArena(poolp, PR_TRUE); if (key != NULL) { SECITEM_ZfreeItem(key, PR_TRUE); } return NULL; }
/* * g e n e r a t e _ S F _ f i l e * * From the supplied manifest file, calculates * digests on the various sections, creating a .SF * file in the process. * */ static int generate_SF_file(char *manifile, char *who) { FILE *sf; FILE *mf; long r1, r2, r3; char whofile[FNSIZE]; char *buf, *name = NULL; JAR_Digest dig; int line = 0; strcpy(whofile, who); if ((mf = fopen(manifile, "rb")) == NULL) { perror(manifile); exit(ERRX); } if ((sf = fopen(whofile, "wb")) == NULL) { perror(who); exit(ERRX); } buf = (char *)PORT_ZAlloc(BUFSIZ); if (buf) name = (char *)PORT_ZAlloc(BUFSIZ); if (buf == NULL || name == NULL) out_of_memory(); fprintf(sf, "Signature-Version: 1.0\n"); fprintf(sf, "Created-By: %s\n", CREATOR); fprintf(sf, "Comments: %s\n", BREAKAGE); if (fgets(buf, BUFSIZ, mf) == NULL) { PR_fprintf(errorFD, "%s: empty manifest file!\n", PROGRAM_NAME); errorCount++; exit(ERRX); } if (strncmp(buf, "Manifest-Version:", 17)) { PR_fprintf(errorFD, "%s: not a manifest file!\n", PROGRAM_NAME); errorCount++; exit(ERRX); } fseek(mf, 0L, SEEK_SET); /* Process blocks of headers, and calculate their hashen */ while (1) { /* Beginning range */ r1 = ftell(mf); if (fgets(name, BUFSIZ, mf) == NULL) break; line++; if (r1 != 0 && strncmp(name, "Name:", 5)) { PR_fprintf(errorFD, "warning: unexpected input in manifest file \"%s\" at line %d:\n", manifile, line); PR_fprintf(errorFD, "%s\n", name); warningCount++; } r2 = r1; while (fgets(buf, BUFSIZ, mf)) { if (*buf == 0 || *buf == '\n' || *buf == '\r') break; line++; /* Ending range for hashing */ r2 = ftell(mf); } r3 = ftell(mf); if (r1) { fprintf(sf, "\n"); fprintf(sf, "%s", name); } calculate_MD5_range(mf, r1, r2, &dig); if (optimize == 0) { fprintf(sf, "Digest-Algorithms: MD5 SHA1\n"); fprintf(sf, "MD5-Digest: %s\n", BTOA_DataToAscii(dig.md5, MD5_LENGTH)); } fprintf(sf, "SHA1-Digest: %s\n", BTOA_DataToAscii(dig.sha1, SHA1_LENGTH)); /* restore normalcy after changing offset position */ fseek(mf, r3, SEEK_SET); } PORT_Free(buf); PORT_Free(name); fclose(sf); fclose(mf); return 0; }
char * crypto_encrypt (const char *cipher, const GByteArray *data, const char *iv, gsize iv_len, const char *key, gsize key_len, gsize *out_len, GError **error) { SECStatus ret; CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD; PK11SlotInfo *slot = NULL; SECItem key_item = { .data = (unsigned char *) key, .len = key_len }; SECItem iv_item = { .data = (unsigned char *) iv, .len = iv_len }; PK11SymKey *sym_key = NULL; SECItem *sec_param = NULL; PK11Context *ctx = NULL; unsigned char *output, *padded_buf; gsize output_len; int encrypted_len = 0, i; gboolean success = FALSE; gsize padded_buf_len, pad_len; if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) cipher_mech = CKM_DES3_CBC_PAD; else { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_UNKNOWN_CIPHER, _("Private key cipher '%s' was unknown."), cipher); return NULL; } /* If data->len % ivlen == 0, then we add another complete block * onto the end so that the decrypter knows there's padding. */ pad_len = iv_len - (data->len % iv_len); output_len = padded_buf_len = data->len + pad_len; padded_buf = g_malloc0 (padded_buf_len); memcpy (padded_buf, data->data, data->len); for (i = 0; i < pad_len; i++) padded_buf[data->len + i] = (guint8) (pad_len & 0xFF); output = g_malloc0 (output_len); if (!output) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_OUT_OF_MEMORY, _("Could not allocate memory for encrypting.")); return NULL; } slot = PK11_GetBestSlot (cipher_mech, NULL); if (!slot) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_INIT_FAILED, _("Failed to initialize the encryption cipher slot.")); goto out; } sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); if (!sym_key) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_SET_KEY_FAILED, _("Failed to set symmetric key for encryption.")); goto out; } sec_param = PK11_ParamFromIV (cipher_mech, &iv_item); if (!sec_param) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_SET_IV_FAILED, _("Failed to set IV for encryption.")); goto out; } ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_ENCRYPT, sym_key, sec_param); if (!ctx) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_INIT_FAILED, _("Failed to initialize the encryption context.")); goto out; } ret = PK11_CipherOp (ctx, output, &encrypted_len, output_len, padded_buf, padded_buf_len); if (ret != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_ENCRYPT_FAILED, _("Failed to encrypt: %d."), PORT_GetError ()); goto out; } if (encrypted_len != output_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_ENCRYPT_FAILED, _("Unexpected amount of data after encrypting.")); goto out; } *out_len = encrypted_len; success = TRUE; out: if (ctx) PK11_DestroyContext (ctx, PR_TRUE); if (sym_key) PK11_FreeSymKey (sym_key); if (sec_param) SECITEM_FreeItem (sec_param, PR_TRUE); if (slot) PK11_FreeSlot (slot); if (padded_buf) { memset (padded_buf, 0, padded_buf_len); g_free (padded_buf); padded_buf = NULL; } if (!success) { memset (output, 0, output_len); g_free (output); output = NULL; } return (char *) output; } NMCryptoFileFormat crypto_verify_cert (const unsigned char *data, gsize len, GError **error) { CERTCertificate *cert; /* Try DER/PEM first */ cert = CERT_DecodeCertFromPackage ((char *) data, len); if (!cert) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CERT_FORMAT_INVALID, _("Couldn't decode certificate: %d"), PORT_GetError()); return NM_CRYPTO_FILE_FORMAT_UNKNOWN; } CERT_DestroyCertificate (cert); return NM_CRYPTO_FILE_FORMAT_X509; } gboolean crypto_verify_pkcs12 (const GByteArray *data, const char *password, GError **error) { SEC_PKCS12DecoderContext *p12ctx = NULL; SECItem pw = { 0 }; PK11SlotInfo *slot = NULL; SECStatus s; char *ucs2_password; glong ucs2_chars = 0; #ifndef WORDS_BIGENDIAN guint16 *p; #endif /* WORDS_BIGENDIAN */ if (error) g_return_val_if_fail (*error == NULL, FALSE); /* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do * any conversions for us. */ if (password && strlen (password)) { ucs2_password = (char *) g_utf8_to_utf16 (password, strlen (password), NULL, &ucs2_chars, NULL); if (!ucs2_password || !ucs2_chars) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_INVALID_PASSWORD, _("Couldn't convert password to UCS2: %d"), PORT_GetError()); return FALSE; } ucs2_chars *= 2; /* convert # UCS2 characters -> bytes */ pw.data = PORT_ZAlloc(ucs2_chars + 2); memcpy (pw.data, ucs2_password, ucs2_chars); pw.len = ucs2_chars + 2; /* include terminating NULL */ memset (ucs2_password, 0, ucs2_chars); g_free (ucs2_password); #ifndef WORDS_BIGENDIAN for (p = (guint16 *) pw.data; p < (guint16 *) (pw.data + pw.len); p++) *p = GUINT16_SWAP_LE_BE (*p); #endif /* WORDS_BIGENDIAN */ } else { /* NULL password */ pw.data = NULL; pw.len = 0; } slot = PK11_GetInternalKeySlot(); p12ctx = SEC_PKCS12DecoderStart (&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL); if (!p12ctx) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_DECODE_FAILED, _("Couldn't initialize PKCS#12 decoder: %d"), PORT_GetError()); goto error; } s = SEC_PKCS12DecoderUpdate (p12ctx, data->data, data->len); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_FILE_FORMAT_INVALID, _("Couldn't decode PKCS#12 file: %d"), PORT_GetError()); goto error; } s = SEC_PKCS12DecoderVerify (p12ctx); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, _("Couldn't verify PKCS#12 file: %d"), PORT_GetError()); goto error; } SEC_PKCS12DecoderFinish (p12ctx); SECITEM_ZfreeItem (&pw, PR_FALSE); return TRUE; error: if (p12ctx) SEC_PKCS12DecoderFinish (p12ctx); if (slot) PK11_FreeSlot(slot); SECITEM_ZfreeItem (&pw, PR_FALSE); return FALSE; }
char *getNSSPassword(PK11SlotInfo *slot, PRBool retry, void *arg) { secuPWData *pwdInfo = (secuPWData *)arg; PRFileDesc *fd; PRInt32 nb; /*number of bytes*/ char* password; char* strings; char* token=NULL; const long maxPwdFileSize = NSSpwdfilesize; int i, tlen=0; if (slot) { token = PK11_GetTokenName(slot); if (token) { tlen = PORT_Strlen(token); /* libreswan_log("authentication needed for token name %s with length %d",token,tlen); */ } else { return 0; } } else { return 0; } if(retry) return 0; strings=PORT_ZAlloc(maxPwdFileSize); if(!strings) { libreswan_log("Not able to allocate memory for reading NSS password file"); return 0; } if(pwdInfo->source == PW_FROMFILE) { if(pwdInfo->data !=NULL) { fd = PR_Open(pwdInfo->data, PR_RDONLY, 0); if (!fd) { PORT_Free(strings); libreswan_log("No password file \"%s\" exists.", pwdInfo->data); return 0; } nb = PR_Read(fd, strings, maxPwdFileSize); PR_Close(fd); if (nb == 0) { libreswan_log("password file contains no data"); PORT_Free(strings); return 0; } i = 0; do { int start = i; int slen; while (strings[i] != '\r' && strings[i] != '\n' && i < nb) i++; strings[i++] = '\0'; while ( (i<nb) && (strings[i] == '\r' || strings[i] == '\n')) { strings[i++] = '\0'; } password = &strings[start]; if (PORT_Strncmp(password, token, tlen)) continue; slen = PORT_Strlen(password); if (slen < (tlen+1)) continue; if (password[tlen] != ':') continue; password = &password[tlen+1]; break; } while (i<nb); password = PORT_Strdup((char*)password); PORT_Free(strings); /* libreswan_log("Password passed to NSS is %s with length %d", password, PORT_Strlen(password)); */ return password; } else { libreswan_log("File with Password to NSS DB is not provided"); return 0; } } libreswan_log("nss password source is not specified as file"); return 0; }
static int nss_cms_recipients_traverse(NSSCMSRecipientInfo **recipientinfos, NSSCMSRecipient **recipient_list) { int count = 0; int rlindex = 0; int i, j; NSSCMSRecipient *rle; NSSCMSRecipientInfo *ri; NSSCMSRecipientEncryptedKey *rek; for (i = 0; recipientinfos[i] != NULL; i++) { ri = recipientinfos[i]; switch (ri->recipientInfoType) { case NSSCMSRecipientInfoID_KeyTrans: if (recipient_list) { NSSCMSRecipientIdentifier *recipId = &ri->ri.keyTransRecipientInfo.recipientIdentifier; if (recipId->identifierType != NSSCMSRecipientID_IssuerSN && recipId->identifierType != NSSCMSRecipientID_SubjectKeyID) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return -1; } /* alloc one & fill it out */ rle = (NSSCMSRecipient *)PORT_ZAlloc(sizeof(NSSCMSRecipient)); if (!rle) return -1; rle->riIndex = i; rle->subIndex = -1; switch (recipId->identifierType) { case NSSCMSRecipientID_IssuerSN: rle->kind = RLIssuerSN; rle->id.issuerAndSN = recipId->id.issuerAndSN; break; case NSSCMSRecipientID_SubjectKeyID: rle->kind = RLSubjKeyID; rle->id.subjectKeyID = recipId->id.subjectKeyID; break; default: /* we never get here because of identifierType check we done before. Leaving it to kill compiler warning */ break; } recipient_list[rlindex++] = rle; } else { count++; } break; case NSSCMSRecipientInfoID_KeyAgree: if (ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys == NULL) break; for (j=0; ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[j] != NULL; j++) { if (recipient_list) { rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[j]; /* alloc one & fill it out */ rle = (NSSCMSRecipient *)PORT_ZAlloc(sizeof(NSSCMSRecipient)); if (!rle) return -1; rle->riIndex = i; rle->subIndex = j; switch (rek->recipientIdentifier.identifierType) { case NSSCMSKeyAgreeRecipientID_IssuerSN: rle->kind = RLIssuerSN; rle->id.issuerAndSN = rek->recipientIdentifier.id.issuerAndSN; break; case NSSCMSKeyAgreeRecipientID_RKeyID: rle->kind = RLSubjKeyID; rle->id.subjectKeyID = rek->recipientIdentifier.id.recipientKeyIdentifier.subjectKeyIdentifier; break; } recipient_list[rlindex++] = rle; } else { count++; } } break; case NSSCMSRecipientInfoID_KEK: /* KEK is not implemented */ break; } } /* if we have a recipient list, we return on success (-1, above, on failure) */ /* otherwise, we return the count. */ if (recipient_list) { recipient_list[rlindex] = NULL; return 0; } else { return count; } }
/* * NSS_CMSCipherContext_StartDecrypt - create a cipher context to do decryption * based on the given bulk encryption key and algorithm identifier (which * may include an iv). * * XXX Once both are working, it might be nice to combine this and the * function below (for starting up encryption) into one routine, and just * have two simple cover functions which call it. */ NSSCMSCipherContext * NSS_CMSCipherContext_StartDecrypt(PK11SymKey *key, SECAlgorithmID *algid) { NSSCMSCipherContext *cc; void *ciphercx; CK_MECHANISM_TYPE cryptoMechType; PK11SlotInfo *slot; SECOidTag algtag; SECItem *param = NULL; algtag = SECOID_GetAlgorithmTag(algid); /* set param and mechanism */ if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { SECItem *pwitem; pwitem = PK11_GetSymKeyUserData(key); if (!pwitem) return NULL; cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); if (cryptoMechType == CKM_INVALID_MECHANISM) { SECITEM_FreeItem(param,PR_TRUE); return NULL; } } else { cryptoMechType = PK11_AlgtagToMechanism(algtag); if ((param = PK11_ParamFromAlgid(algid)) == NULL) return NULL; } cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext)); if (cc == NULL) { SECITEM_FreeItem(param,PR_TRUE); return NULL; } /* figure out pad and block sizes */ cc->pad_size = PK11_GetBlockSize(cryptoMechType, param); slot = PK11_GetSlotFromKey(key); cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size; PK11_FreeSlot(slot); /* create PK11 cipher context */ ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT, key, param); SECITEM_FreeItem(param, PR_TRUE); if (ciphercx == NULL) { PORT_Free (cc); return NULL; } cc->cx = ciphercx; cc->doit = (nss_cms_cipher_function) PK11_CipherOp; cc->destroy = (nss_cms_cipher_destroy) PK11_DestroyContext; cc->encrypt = PR_FALSE; cc->pending_count = 0; return cc; }
/* * NSS_CMSCipherContext_StartEncrypt - create a cipher object to do encryption, * based on the given bulk encryption key and algorithm tag. Fill in the * algorithm identifier (which may include an iv) appropriately. * * XXX Once both are working, it might be nice to combine this and the * function above (for starting up decryption) into one routine, and just * have two simple cover functions which call it. */ NSSCMSCipherContext * NSS_CMSCipherContext_StartEncrypt(PRArenaPool *poolp, PK11SymKey *key, SECAlgorithmID *algid) { NSSCMSCipherContext *cc; void *ciphercx; SECStatus rv; CK_MECHANISM_TYPE cryptoMechType; PK11SlotInfo *slot; SECItem *param = NULL; PRBool needToEncodeAlgid = PR_FALSE; SECOidTag algtag = SECOID_GetAlgorithmTag(algid); /* set param and mechanism */ if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { SECItem *pwitem; pwitem = PK11_GetSymKeyUserData(key); if (!pwitem) return NULL; cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); if (cryptoMechType == CKM_INVALID_MECHANISM) { SECITEM_FreeItem(param,PR_TRUE); return NULL; } } else { cryptoMechType = PK11_AlgtagToMechanism(algtag); if ((param = PK11_GenerateNewParam(cryptoMechType, key)) == NULL) return NULL; needToEncodeAlgid = PR_TRUE; } cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext)); if (cc == NULL) { goto loser; } /* now find pad and block sizes for our mechanism */ cc->pad_size = PK11_GetBlockSize(cryptoMechType, param); slot = PK11_GetSlotFromKey(key); cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size; PK11_FreeSlot(slot); /* and here we go, creating a PK11 cipher context */ ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT, key, param); if (ciphercx == NULL) { PORT_Free(cc); cc = NULL; goto loser; } /* * These are placed after the CreateContextBySymKey() because some * mechanisms have to generate their IVs from their card (i.e. FORTEZZA). * Don't move it from here. * XXX is that right? the purpose of this is to get the correct algid * containing the IVs etc. for encoding. this means we need to set this up * BEFORE encoding the algid in the contentInfo, right? */ if (needToEncodeAlgid) { rv = PK11_ParamToAlgid(algtag, param, poolp, algid); if(rv != SECSuccess) { PORT_Free(cc); cc = NULL; goto loser; } } cc->cx = ciphercx; cc->doit = (nss_cms_cipher_function)PK11_CipherOp; cc->destroy = (nss_cms_cipher_destroy)PK11_DestroyContext; cc->encrypt = PR_TRUE; cc->pending_count = 0; loser: SECITEM_FreeItem(param, PR_TRUE); return cc; }
/**************************************************************** * * J z i p A d d * * Adds a new file into a ZIP file. The ZIP file must have already * been opened with JzipOpen. */ int JzipAdd(char *fullname, char *filename, ZIPfile *zipfile, int compression_level) { ZIPentry * entry; PRFileDesc * readfp; PRFileDesc * zipfp; unsigned long crc; unsigned long local_size_pos; int num; int err; int deflate_percent; z_stream zstream; Bytef inbuf[BUFSIZ]; Bytef outbuf[BUFSIZ]; if ( !fullname || !filename || !zipfile) { return - 1; } zipfp = zipfile->fp; if (!zipfp) return - 1; if ( (readfp = PR_Open(fullname, PR_RDONLY, 0777)) == NULL) { char *nsprErr; if (PR_GetErrorTextLength()) { nsprErr = PR_Malloc(PR_GetErrorTextLength()); PR_GetErrorText(nsprErr); } else { nsprErr = NULL; } PR_fprintf(errorFD, "%s: %s\n", fullname, nsprErr ? nsprErr : ""); errorCount++; if (nsprErr) PR_Free(nsprErr); exit(ERRX); } /* * Make sure the input file is not the output file. * Add a few bytes to the end of the JAR file and see if the input file * twitches */ { PRInt32 endOfJar; PRInt32 inputSize; PRBool isSame; inputSize = PR_Available(readfp); endOfJar = PR_Seek(zipfp, 0L, PR_SEEK_CUR); if (PR_Write(zipfp, "abcde", 5) < 5) { char *nsprErr; if (PR_GetErrorTextLength()) { nsprErr = PR_Malloc(PR_GetErrorTextLength()); PR_GetErrorText(nsprErr); } else { nsprErr = NULL; } PR_fprintf(errorFD, "Writing to zip file: %s\n", nsprErr ? nsprErr : ""); if (nsprErr) PR_Free(nsprErr); errorCount++; exit(ERRX); } isSame = (PR_Available(readfp) != inputSize); PR_Seek(zipfp, endOfJar, PR_SEEK_SET); if (isSame) { /* It's the same file! Forget it! */ PR_Close(readfp); return 0; } } if (verbosity >= 0) { PR_fprintf(outputFD, "adding %s to %s...", fullname, zipfile->filename); } entry = PORT_ZAlloc(sizeof(ZIPentry)); if (!entry) out_of_memory(); entry->filename = PORT_Strdup(filename); entry->comment = NULL; /* Set up local file header */ longtox(LSIG, entry->local.signature); inttox(strlen(filename), entry->local.filename_len); inttox(zipfile->time, entry->local.time); inttox(zipfile->date, entry->local.date); inttox(Z_DEFLATED, entry->local.method); /* Set up central directory entry */ longtox(CSIG, entry->central.signature); inttox(strlen(filename), entry->central.filename_len); if (entry->comment) { inttox(strlen(entry->comment), entry->central.commentfield_len); } longtox(PR_Seek(zipfile->fp, 0, PR_SEEK_CUR), entry->central.localhdr_offset); inttox(zipfile->time, entry->central.time); inttox(zipfile->date, entry->central.date); inttox(Z_DEFLATED, entry->central.method); /* Compute crc. Too bad we have to process the whole file to do this*/ crc = crc32(0L, NULL, 0); while ( (num = PR_Read(readfp, inbuf, BUFSIZ)) > 0) { crc = crc32(crc, inbuf, num); } PR_Seek(readfp, 0L, PR_SEEK_SET); /* Store CRC */ longtox(crc, entry->local.crc32); longtox(crc, entry->central.crc32); /* Stick this entry onto the end of the list */ entry->next = NULL; if ( zipfile->list == NULL ) { /* First entry */ zipfile->list = entry; } else { ZIPentry * pe; pe = zipfile->list; while (pe->next != NULL) { pe = pe->next; } pe->next = entry; } /* * Start writing stuff out */ local_size_pos = PR_Seek(zipfp, 0, PR_SEEK_CUR) + 18; /* File header */ if (PR_Write(zipfp, &entry->local, sizeof(struct ZipLocal )) < sizeof(struct ZipLocal )) { char *nsprErr; if (PR_GetErrorTextLength()) { nsprErr = PR_Malloc(PR_GetErrorTextLength()); PR_GetErrorText(nsprErr); } else { nsprErr = NULL; } PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : ""); if (nsprErr) PR_Free(nsprErr); errorCount++; exit(ERRX); } /* File Name */ if ( PR_Write(zipfp, filename, strlen(filename)) < strlen(filename)) { char *nsprErr; if (PR_GetErrorTextLength()) { nsprErr = PR_Malloc(PR_GetErrorTextLength()); PR_GetErrorText(nsprErr); } else { nsprErr = NULL; } PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : ""); if (nsprErr) PR_Free(nsprErr); errorCount++; exit(ERRX); } /* * File data */ /* Initialize zstream */ zstream.zalloc = my_alloc_func; zstream.zfree = my_free_func; zstream.opaque = NULL; zstream.next_in = inbuf; zstream.avail_in = BUFSIZ; zstream.next_out = outbuf; zstream.avail_out = BUFSIZ; /* Setting the windowBits to -MAX_WBITS is an undocumented feature of * zlib (see deflate.c in zlib). It is the same thing that Java does * when you specify the nowrap option for deflation in java.util.zip. * It causes zlib to leave out its headers and footers, which don't * work in PKZIP files. */ err = deflateInit2(&zstream, compression_level, Z_DEFLATED, -MAX_WBITS, 8 /*default*/, Z_DEFAULT_STRATEGY); if (err != Z_OK) { handle_zerror(err, zstream.msg); exit(ERRX); } while ( (zstream.avail_in = PR_Read(readfp, inbuf, BUFSIZ)) > 0) { zstream.next_in = inbuf; /* Process this chunk of data */ while (zstream.avail_in > 0) { err = deflate(&zstream, Z_NO_FLUSH); if (err != Z_OK) { handle_zerror(err, zstream.msg); exit(ERRX); } if (zstream.avail_out <= 0) { if ( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) { char *nsprErr; if (PR_GetErrorTextLength()) { nsprErr = PR_Malloc(PR_GetErrorTextLength()); PR_GetErrorText(nsprErr); } else { nsprErr = NULL; } PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : ""); if (nsprErr) PR_Free(nsprErr); errorCount++; exit(ERRX); } zstream.next_out = outbuf; zstream.avail_out = BUFSIZ; } } } /* Now flush everything */ while (1) { err = deflate(&zstream, Z_FINISH); if (err == Z_STREAM_END) { break; } else if (err == Z_OK) { /* output buffer full, repeat */ } else { handle_zerror(err, zstream.msg); exit(ERRX); } if ( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) { char *nsprErr; if (PR_GetErrorTextLength()) { nsprErr = PR_Malloc(PR_GetErrorTextLength()); PR_GetErrorText(nsprErr); } else { nsprErr = NULL; } PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : ""); if (nsprErr) PR_Free(nsprErr); errorCount++; exit(ERRX); } zstream.avail_out = BUFSIZ; zstream.next_out = outbuf; } /* If there's any output left, write it out. */ if (zstream.next_out != outbuf) { if ( PR_Write(zipfp, outbuf, zstream.next_out - outbuf) < zstream.next_out - outbuf) { char *nsprErr; if (PR_GetErrorTextLength()) { nsprErr = PR_Malloc(PR_GetErrorTextLength()); PR_GetErrorText(nsprErr); } else { nsprErr = NULL; } PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : ""); if (nsprErr) PR_Free(nsprErr); errorCount++; exit(ERRX); } zstream.avail_out = BUFSIZ; zstream.next_out = outbuf; } /* Now that we know the compressed size, write this to the headers */ longtox(zstream.total_in, entry->local.orglen); longtox(zstream.total_out, entry->local.size); if (PR_Seek(zipfp, local_size_pos, PR_SEEK_SET) == -1) { char *nsprErr; if (PR_GetErrorTextLength()) { nsprErr = PR_Malloc(PR_GetErrorTextLength()); PR_GetErrorText(nsprErr); } else { nsprErr = NULL; } PR_fprintf(errorFD, "Accessing zip file: %s\n", nsprErr ? nsprErr : ""); if (nsprErr) PR_Free(nsprErr); errorCount++; exit(ERRX); } if ( PR_Write(zipfp, entry->local.size, 8) != 8) { char *nsprErr; if (PR_GetErrorTextLength()) { nsprErr = PR_Malloc(PR_GetErrorTextLength()); PR_GetErrorText(nsprErr); } else { nsprErr = NULL; } PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : ""); if (nsprErr) PR_Free(nsprErr); errorCount++; exit(ERRX); } if (PR_Seek(zipfp, 0L, PR_SEEK_END) == -1) { char *nsprErr; if (PR_GetErrorTextLength()) { nsprErr = PR_Malloc(PR_GetErrorTextLength()); PR_GetErrorText(nsprErr); } else { nsprErr = NULL; } PR_fprintf(errorFD, "Accessing zip file: %s\n", nsprErr ? nsprErr : ""); if (nsprErr) PR_Free(nsprErr); errorCount++; exit(ERRX); } longtox(zstream.total_in, entry->central.orglen); longtox(zstream.total_out, entry->central.size); /* Close out the deflation operation */ err = deflateEnd(&zstream); if (err != Z_OK) { handle_zerror(err, zstream.msg); exit(ERRX); } PR_Close(readfp); if ((zstream.total_in > zstream.total_out) && (zstream.total_in > 0)) { deflate_percent = (int) ((zstream.total_in - zstream.total_out) *100 / zstream.total_in); } else { deflate_percent = 0; } if (verbosity >= 0) { PR_fprintf(outputFD, "(deflated %d%%)\n", deflate_percent); } return 0; }
static SEC_PKCS7EncoderContext * sec_pkcs7_encoder_start_contexts (SEC_PKCS7ContentInfo *cinfo, PK11SymKey *bulkkey) { SEC_PKCS7EncoderContext *p7ecx; SECOidTag kind; PRBool encrypt; SECItem **digests; SECAlgorithmID *digestalg, **digestalgs; p7ecx = (SEC_PKCS7EncoderContext*)PORT_ZAlloc (sizeof(SEC_PKCS7EncoderContext)); if (p7ecx == NULL) return NULL; digests = NULL; digestalg = NULL; digestalgs = NULL; encrypt = PR_FALSE; kind = SEC_PKCS7ContentType (cinfo); switch (kind) { default: case SEC_OID_PKCS7_DATA: break; case SEC_OID_PKCS7_DIGESTED_DATA: digestalg = &(cinfo->content.digestedData->digestAlg); break; case SEC_OID_PKCS7_SIGNED_DATA: digests = cinfo->content.signedData->digests; digestalgs = cinfo->content.signedData->digestAlgorithms; break; case SEC_OID_PKCS7_ENCRYPTED_DATA: case SEC_OID_PKCS7_ENVELOPED_DATA: encrypt = PR_TRUE; break; case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: digests = cinfo->content.signedAndEnvelopedData->digests; digestalgs = cinfo->content.signedAndEnvelopedData->digestAlgorithms; encrypt = PR_TRUE; break; } if (encrypt) { p7ecx->encryptobj = sec_pkcs7_encoder_start_encrypt (cinfo, bulkkey); if (p7ecx->encryptobj == NULL) { PORT_Free (p7ecx); return NULL; } } if (digestalgs != NULL) { if (digests != NULL) { /* digests already created (probably for detached data) */ digestalg = NULL; } else { /* * XXX Some day we should handle multiple digests; for now, * assume only one will be done. */ PORT_Assert (digestalgs[0] != NULL && digestalgs[1] == NULL); digestalg = digestalgs[0]; } } if (digestalg != NULL) { SECOidTag oidTag = SECOID_FindOIDTag(&(digestalg->algorithm)); p7ecx->digestobj = HASH_GetHashObjectByOidTag(oidTag); if (p7ecx->digestobj != NULL) { p7ecx->digestcx = (* p7ecx->digestobj->create) (); if (p7ecx->digestcx == NULL) p7ecx->digestobj = NULL; else (* p7ecx->digestobj->begin) (p7ecx->digestcx); } if (p7ecx->digestobj == NULL) { if (p7ecx->encryptobj != NULL) sec_PKCS7DestroyEncryptObject (p7ecx->encryptobj); PORT_Free (p7ecx); return NULL; } } p7ecx->cinfo = cinfo; return p7ecx; }
/* Returns the password passed in in the text file. * Uses the password once and nulls it out the prevent * PKCS11 from calling us forever. */ char *GetFilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg) { char* phrases, *phrase; PRFileDesc *fd; PRInt32 nb; const char *pwFile = (const char *)arg; int i; const long maxPwdFileSize = 4096; char* tokenName = NULL; int tokenLen = 0; if (!pwFile) { return 0; } if (retry) { return 0; /* no good retrying - the files contents will be the same */ } phrases = PORT_ZAlloc(maxPwdFileSize); if (!phrases) { return 0; /* out of memory */ } fd = PR_Open(pwFile, PR_RDONLY, 0); if (!fd) { fprintf(stderr, "No password file \"%s\" exists.\n", pwFile); PORT_Free(phrases); return NULL; } nb = PR_Read(fd, phrases, maxPwdFileSize); PR_Close(fd); if (nb == 0) { fprintf(stderr,"password file contains no data\n"); PORT_Free(phrases); return NULL; } if (slot) { tokenName = PK11_GetTokenName(slot); if (tokenName) { tokenLen = PORT_Strlen(tokenName); } } i = 0; do { int startphrase = i; int phraseLen; /* handle the Windows EOL case */ while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb) i++; /* terminate passphrase */ phrases[i++] = '\0'; /* clean up any EOL before the start of the next passphrase */ while ( (i<nb) && (phrases[i] == '\r' || phrases[i] == '\n')) { phrases[i++] = '\0'; } /* now analyze the current passphrase */ phrase = &phrases[startphrase]; if (!tokenName) break; if (PORT_Strncmp(phrase, tokenName, tokenLen)) continue; phraseLen = PORT_Strlen(phrase); if (phraseLen < (tokenLen+1)) continue; if (phrase[tokenLen] != ':') continue; phrase = &phrase[tokenLen+1]; break; } while (i<nb); phrase = PORT_Strdup((char*)phrase); PORT_Free(phrases); return phrase; }