/* * Prepare a buffer for any padded CBC encryption algorithm, growing to the * appropriate boundary and filling with the appropriate padding. * blockSize must be a power of 2. * * NOTE: If arena is non-NULL, we re-allocate from there, otherwise * we assume (and use) XP memory (re)allocation. */ unsigned char * CBC_PadBuffer(PLArenaPool *arena, unsigned char *inbuf, unsigned int inlen, unsigned int *outlen, int blockSize) { unsigned char *outbuf; unsigned int des_len; unsigned int i; unsigned char des_pad_len; /* * We need from 1 to blockSize bytes -- we *always* grow. * The extra bytes contain the value of the length of the padding: * if we have 2 bytes of padding, then the padding is "0x02, 0x02". */ des_len = (inlen + blockSize) & ~(blockSize - 1); if (arena != NULL) { outbuf = (unsigned char *)PORT_ArenaGrow(arena, inbuf, inlen, des_len); } else { outbuf = (unsigned char *)PORT_Realloc(inbuf, des_len); } if (outbuf == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; } des_pad_len = des_len - inlen; for (i = inlen; i < des_len; i++) outbuf[i] = des_pad_len; *outlen = des_len; return outbuf; }
/* appends a shrouded key to a key bag. this is used for exporting * to store externally wrapped keys. it is used when importing to convert * old items to new */ SECStatus sec_pkcs12_append_shrouded_key(SEC_PKCS12BaggageItem *bag, SEC_PKCS12ESPVKItem *espvk) { int size; void *mark = NULL, *dummy = NULL; if((bag == NULL) || (espvk == NULL)) return SECFailure; mark = PORT_ArenaMark(bag->poolp); /* grow the list */ size = (bag->nEspvks + 1) * sizeof(SEC_PKCS12ESPVKItem *); dummy = (SEC_PKCS12ESPVKItem **)PORT_ArenaGrow(bag->poolp, bag->espvks, size, size + sizeof(SEC_PKCS12ESPVKItem *)); bag->espvks = (SEC_PKCS12ESPVKItem**)dummy; if(dummy == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } bag->espvks[bag->nEspvks] = espvk; bag->nEspvks++; bag->espvks[bag->nEspvks] = NULL; PORT_ArenaUnmark(bag->poolp, mark); return SECSuccess; loser: PORT_ArenaRelease(bag->poolp, mark); return SECFailure; }
/* * NSS_CMSArray_Add - add an element to the end of an array * * The array of pointers is either created (if array was empty before) or grown. */ SECStatus NSS_CMSArray_Add(PRArenaPool *poolp, void ***array, void *obj) { void **p; int n; void **dest; PORT_Assert(array != NULL); if (array == NULL) return SECFailure; if (*array == NULL) { dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *)); n = 0; } else { n = 0; p = *array; while (*p++) n++; dest = (void **)PORT_ArenaGrow (poolp, *array, (n + 1) * sizeof(void *), (n + 2) * sizeof(void *)); } if (dest == NULL) return SECFailure; dest[n] = obj; dest[n+1] = NULL; *array = dest; return SECSuccess; }
SECStatus SECITEM_ReallocItemV2(PLArenaPool *arena, SECItem *item, unsigned int newlen) { unsigned char *newdata = NULL; PORT_Assert(item); if (!item) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } if (item->len == newlen) { return SECSuccess; } if (!newlen) { if (!arena) { PORT_Free(item->data); } item->data = NULL; item->len = 0; return SECSuccess; } if (!item->data) { /* allocate fresh block of memory */ PORT_Assert(!item->len); if (arena) { newdata = PORT_ArenaAlloc(arena, newlen); } else { newdata = PORT_Alloc(newlen); } } else { /* reallocate or adjust existing block of memory */ if (arena) { if (item->len > newlen) { /* There's no need to realloc a shorter block from the arena, * because it would result in using even more memory! * Therefore we'll continue to use the old block and * set the item to the shorter size. */ item->len = newlen; return SECSuccess; } newdata = PORT_ArenaGrow(arena, item->data, item->len, newlen); } else { newdata = PORT_Realloc(item->data, newlen); } } if (!newdata) { PORT_SetError(SEC_ERROR_NO_MEMORY); return SECFailure; } item->len = newlen; item->data = newdata; return SECSuccess; }
SECStatus SECITEM_ReallocItem(PLArenaPool *arena, SECItem *item, unsigned int oldlen, unsigned int newlen) { PORT_Assert(item != NULL); if (item == NULL) { /* XXX Set error. But to what? */ return SECFailure; } /* * If no old length, degenerate to just plain alloc. */ if (oldlen == 0) { PORT_Assert(item->data == NULL || item->len == 0); if (newlen == 0) { /* Nothing to do. Weird, but not a failure. */ return SECSuccess; } item->len = newlen; if (arena != NULL) { item->data = PORT_ArenaAlloc(arena, newlen); } else { item->data = PORT_Alloc(newlen); } } else { if (arena != NULL) { item->data = PORT_ArenaGrow(arena, item->data, oldlen, newlen); } else { item->data = PORT_Realloc(item->data, newlen); } } if (item->data == NULL) { return SECFailure; } return SECSuccess; }
/* * SecCmsArrayAdd - add an element to the end of an array * * The array of pointers is either created (if array was empty before) or grown. */ OSStatus SecCmsArrayAdd(PRArenaPool *poolp, void ***array, void *obj) { void **p; int n; void **dest; PORT_Assert(array != NULL); if (array == NULL) return SECFailure; if (*array == NULL) { dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *)); n = 0; } else { n = 0; p = *array; while (*p++) n++; if (n>=(int)((INT_MAX/sizeof(void *))-2)) { // Prevent under-allocation due to integer overflow return SECFailure; } dest = (void **)PORT_ArenaGrow (poolp, *array, (n + 1) * sizeof(void *), (n + 2) * sizeof(void *)); } if (dest == NULL) return SECFailure; dest[n] = obj; dest[n+1] = NULL; *array = dest; return SECSuccess; }
/* create a new external bag which is appended onto the list * of bags in baggage. the bag is created in the same arena * as baggage */ SEC_PKCS12BaggageItem * sec_pkcs12_create_external_bag(SEC_PKCS12Baggage *luggage) { void *dummy, *mark; SEC_PKCS12BaggageItem *bag; if(luggage == NULL) { return NULL; } mark = PORT_ArenaMark(luggage->poolp); /* allocate space for null terminated bag list */ if(luggage->bags == NULL) { luggage->bags=(SEC_PKCS12BaggageItem**)PORT_ArenaZAlloc(luggage->poolp, sizeof(SEC_PKCS12BaggageItem *)); if(luggage->bags == NULL) { goto loser; } luggage->luggage_size = 0; } /* grow the list */ dummy = PORT_ArenaGrow(luggage->poolp, luggage->bags, sizeof(SEC_PKCS12BaggageItem *) * (luggage->luggage_size + 1), sizeof(SEC_PKCS12BaggageItem *) * (luggage->luggage_size + 2)); if(dummy == NULL) { goto loser; } luggage->bags = (SEC_PKCS12BaggageItem**)dummy; luggage->bags[luggage->luggage_size] = (SEC_PKCS12BaggageItem *)PORT_ArenaZAlloc(luggage->poolp, sizeof(SEC_PKCS12BaggageItem)); if(luggage->bags[luggage->luggage_size] == NULL) { goto loser; } /* create new bag and append it to the end */ bag = luggage->bags[luggage->luggage_size]; bag->espvks = (SEC_PKCS12ESPVKItem **)PORT_ArenaZAlloc( luggage->poolp, sizeof(SEC_PKCS12ESPVKItem *)); bag->unencSecrets = (SEC_PKCS12SafeBag **)PORT_ArenaZAlloc( luggage->poolp, sizeof(SEC_PKCS12SafeBag *)); if((bag->espvks == NULL) || (bag->unencSecrets == NULL)) { goto loser; } bag->poolp = luggage->poolp; luggage->luggage_size++; luggage->bags[luggage->luggage_size] = NULL; bag->espvks[0] = NULL; bag->unencSecrets[0] = NULL; bag->nEspvks = bag->nSecrets = 0; PORT_ArenaUnmark(luggage->poolp, mark); return bag; loser: PORT_ArenaRelease(luggage->poolp, mark); PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; }
/* this function converts a password to unicode and encures that the * required double 0 byte be placed at the end of the string */ PRBool sec_pkcs12_convert_item_to_unicode(PRArenaPool *arena, SECItem *dest, SECItem *src, PRBool zeroTerm, PRBool asciiConvert, PRBool toUnicode) { PRBool success = PR_FALSE; if(!src || !dest) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return PR_FALSE; } dest->len = src->len * 3 + 2; if(arena) { dest->data = (unsigned char*)PORT_ArenaZAlloc(arena, dest->len); } else { dest->data = (unsigned char*)PORT_ZAlloc(dest->len); } if(!dest->data) { dest->len = 0; return PR_FALSE; } if(!asciiConvert) { success = PORT_UCS2_UTF8Conversion(toUnicode, src->data, src->len, dest->data, dest->len, &dest->len); } else { #ifndef IS_LITTLE_ENDIAN PRBool swapUnicode = PR_FALSE; #else PRBool swapUnicode = PR_TRUE; #endif success = PORT_UCS2_ASCIIConversion(toUnicode, src->data, src->len, dest->data, dest->len, &dest->len, swapUnicode); } if(!success) { if(!arena) { PORT_Free(dest->data); dest->data = NULL; dest->len = 0; } return PR_FALSE; } if((dest->data[dest->len-1] || dest->data[dest->len-2]) && zeroTerm) { if(dest->len + 2 > 3 * src->len) { if(arena) { dest->data = (unsigned char*)PORT_ArenaGrow(arena, dest->data, dest->len, dest->len + 2); } else { dest->data = (unsigned char*)PORT_Realloc(dest->data, dest->len + 2); } if(!dest->data) { return PR_FALSE; } } dest->len += 2; dest->data[dest->len-1] = dest->data[dest->len-2] = 0; } return PR_TRUE; }