/** Create DSA parameters @param prng An active PRNG state @param wprng The index of the PRNG desired @param group_size Size of the multiplicative group (octets) @param modulus_size Size of the modulus (octets) @param p [out] bignum where generated 'p' is stored (must be initialized by caller) @param q [out] bignum where generated 'q' is stored (must be initialized by caller) @param g [out] bignum where generated 'g' is stored (must be initialized by caller) @return CRYPT_OK if successful, upon error this function will free all allocated memory */ static int dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g) { unsigned long L, N, n, outbytes, seedbytes, counter, j, i; int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash; unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE]; void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc; /* check size */ if (group_size >= LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size) { return CRYPT_INVALID_ARG; } /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function * * L = The desired length of the prime p (in bits e.g. L = 1024) * N = The desired length of the prime q (in bits e.g. N = 160) * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N * outlen = The bit length of Hash function * * 1. Check that the (L, N) * 2. If (seedlen <N), then return INVALID. * 3. n = ceil(L / outlen) - 1 * 4. b = L- 1 - (n * outlen) * 5. domain_parameter_seed = an arbitrary sequence of seedlen bits * 6. U = Hash (domain_parameter_seed) mod 2^(N-1) * 7. q = 2^(N-1) + U + 1 - (U mod 2) * 8. Test whether or not q is prime as specified in Appendix C.3 * 9. If qis not a prime, then go to step 5. * 10. offset = 1 * 11. For counter = 0 to (4L- 1) do { * For j=0 to n do { * Vj = Hash ((domain_parameter_seed+ offset + j) mod 2^seedlen * } * W = V0 + (V1 *2^outlen) + ... + (Vn-1 * 2^((n-1) * outlen)) + ((Vn mod 2^b) * 2^(n * outlen)) * X = W + 2^(L-1) Comment: 0 <= W < 2^(L-1); hence 2^(L-1) <= X < 2^L * c = X mod 2*q * p = X - (c - 1) Comment: p ~ 1 (mod 2*q) * If (p >= 2^(L-1)) { * Test whether or not p is prime as specified in Appendix C.3. * If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter * } * offset = offset + n + 1 Comment: Increment offset * } */ seedbytes = group_size; L = modulus_size * 8; N = group_size * 8; /* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ mr_tests_p = (L <= 2048) ? 3 : 2; if (N <= 160) { mr_tests_q = 19; } else if (N <= 224) { mr_tests_q = 24; } else { mr_tests_q = 27; } if (N <= 256) { hash = register_hash(&sha256_desc); } else if (N <= 384) { hash = register_hash(&sha384_desc); } else if (N <= 512) { hash = register_hash(&sha512_desc); } else { return CRYPT_INVALID_ARG; /* group_size too big */ } if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } outbytes = hash_descriptor[hash]->hashsize; n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1; if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; } if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; } err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, NULL); if (err != CRYPT_OK) { goto cleanup1; } if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; } /* t2L1 = 2^(L-1) */ if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; } /* t2N1 = 2^(N-1) */ if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; } /* t2seedlen = 2^seedlen */ for(found_p=0; !found_p;) { /* q */ for(found_q=0; !found_q;) { if (prng_descriptor[wprng]->read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; } i = outbytes; if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; } if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; } if ((err = mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; } if (!mp_isodd(q)) mp_add_d(q, 1, q); if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; } /* XXX-TODO rounds are ignored; no Lucas test */ if (res == LTC_MP_YES) found_q = 1; } /* p */ if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; } if ((err = mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; } for(counter=0; counter < 4*L && !found_p; counter++) { for(j=0; j<=n; j++) { if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; } /* seedinc = (seedinc+1) % 2^seed_bitlen */ if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; } zeromem(sbuf, seedbytes); if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; } i = outbytes; err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i); if (err != CRYPT_OK) { goto cleanup; } } if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; } if ((err = mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; } if ((err = mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; } if ((err = mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; } if (mp_cmp(p, t2L1) != LTC_MP_LT) { /* p >= 2^(L-1) */ if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; } /* XXX-TODO rounds are ignored; no Lucas test */ if (res == LTC_MP_YES) { found_p = 1; } } } } /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g * 1. e = (p - 1)/q * 2. h = any integer satisfying: 1 < h < (p - 1) * h could be obtained from a random number generator or from a counter that changes after each use * 3. g = h^e mod p * 4. if (g == 1), then go to step 2. * */ if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; } if ((err = mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; } /* e = (p - 1)/q */ i = mp_count_bits(p); do { do { if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; } } while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT); if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; } /* h is randon and 1 < h < (p-1) */ if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; } } while (mp_cmp_d(g, 1) == LTC_MP_EQ); err = CRYPT_OK; cleanup: mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, NULL); cleanup1: XFREE(sbuf); cleanup2: XFREE(wbuf); cleanup3: return err; }
/* alloc user allocs to work with zlib */ static void* myAlloc(void* opaque, unsigned int item, unsigned int size) { (void)opaque; return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ); }
/** PKCS #1 pad then sign @param in The hash to sign @param inlen The length of the hash to sign (octets) @param out [out] The signature @param outlen [in/out] The max size and resulting size of the signature @param padding Type of padding (LTC_PKCS_1_PSS or LTC_PKCS_1_V1_5) @param prng An active PRNG state @param prng_idx The index of the PRNG desired @param hash_idx The index of the hash desired @param saltlen The length of the salt desired (octets) @param key The private RSA key to use @return CRYPT_OK if successful */ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int padding, prng_state *prng, int prng_idx, int hash_idx, unsigned long saltlen, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x, y; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* valid padding? */ if ((padding != LTC_PKCS_1_V1_5) && (padding != LTC_PKCS_1_PSS)) { return CRYPT_PK_INVALID_PADDING; } if (padding == LTC_PKCS_1_PSS) { /* valid prng and hash ? */ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } } /* get modulus len in bits */ modulus_bitlen = mp_count_bits((key->N)); /* outlen must be at least the size of the modulus */ modulus_bytelen = mp_unsigned_bin_size((key->N)); if (modulus_bytelen > *outlen) { *outlen = modulus_bytelen; return CRYPT_BUFFER_OVERFLOW; } if (padding == LTC_PKCS_1_PSS) { /* PSS pad the key */ x = *outlen; if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx, hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { return err; } } else { /* PKCS #1 v1.5 pad the hash */ unsigned char *tmpin; ltc_asn1_list digestinfo[2], siginfo[2]; /* not all hashes have OIDs... so sad */ if (hash_descriptor[hash_idx]->OIDlen == 0) { return CRYPT_INVALID_ARG; } /* construct the SEQUENCE SEQUENCE { SEQUENCE {hashoid OID blah NULL } hash OCTET STRING } */ LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx]->OID, hash_descriptor[hash_idx]->OIDlen); LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen); /* allocate memory for the encoding */ y = mp_unsigned_bin_size(key->N); tmpin = XMALLOC(y); if (tmpin == NULL) { return CRYPT_MEM; } if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) { XFREE(tmpin); return err; } x = *outlen; if ((err = pkcs_1_v1_5_encode(tmpin, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x)) != CRYPT_OK) { XFREE(tmpin); return err; } XFREE(tmpin); } /* RSA encode it */ return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); }
int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) { byte* ocspReqBuf = NULL; int ocspReqSz = 2048; byte* ocspRespBuf = NULL; int result = -1; OCSP_Entry* ocspe; CertStatus* certStatus = NULL; const char *url; int urlSz; #ifdef WOLFSSL_SMALL_STACK CertStatus* newStatus; OcspRequest* ocspRequest; OcspResponse* ocspResponse; #else CertStatus newStatus[1]; OcspRequest ocspRequest[1]; OcspResponse ocspResponse[1]; #endif WOLFSSL_ENTER("CheckCertOCSP"); if (LockMutex(&ocsp->ocspLock) != 0) { WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); return BAD_MUTEX_E; } ocspe = ocsp->ocspList; while (ocspe) { if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0 && XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE) == 0) break; else ocspe = ocspe->next; } if (ocspe == NULL) { ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry), NULL, DYNAMIC_TYPE_OCSP_ENTRY); if (ocspe != NULL) { InitOCSP_Entry(ocspe, cert); ocspe->next = ocsp->ocspList; ocsp->ocspList = ocspe; } else { UnLockMutex(&ocsp->ocspLock); WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); return MEMORY_ERROR; } } else { certStatus = ocspe->status; while (certStatus) { if (certStatus->serialSz == cert->serialSz && XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0) break; else certStatus = certStatus->next; } } if (certStatus != NULL) { if (!ValidateDate(certStatus->thisDate, certStatus->thisDateFormat, BEFORE) || (certStatus->nextDate[0] == 0) || !ValidateDate(certStatus->nextDate, certStatus->nextDateFormat, AFTER)) { WOLFSSL_MSG("\tinvalid status date, looking up cert"); } else { result = xstat2err(certStatus->status); UnLockMutex(&ocsp->ocspLock); WOLFSSL_LEAVE("CheckCertOCSP", result); return result; } } UnLockMutex(&ocsp->ocspLock); if (ocsp->cm->ocspUseOverrideURL) { url = ocsp->cm->ocspOverrideURL; if (url != NULL && url[0] != '\0') urlSz = (int)XSTRLEN(url); else return OCSP_NEED_URL; } else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) { url = (const char *)cert->extAuthInfo; urlSz = cert->extAuthInfoSz; } else { /* cert doesn't have extAuthInfo, assuming CERT_GOOD */ return 0; } ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER); if (ocspReqBuf == NULL) { WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); return MEMORY_ERROR; } #ifdef WOLFSSL_SMALL_STACK newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, DYNAMIC_TYPE_TMP_BUFFER); ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, DYNAMIC_TYPE_TMP_BUFFER); ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (newStatus == NULL || ocspRequest == NULL || ocspResponse == NULL) { if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ocspRequest) XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); return MEMORY_E; } #endif InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, ocspReqBuf, ocspReqSz); ocspReqSz = EncodeOcspRequest(ocspRequest); if (ocsp->cm->ocspIOCb) result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, ocspReqBuf, ocspReqSz, &ocspRespBuf); if (result >= 0 && ocspRespBuf) { XMEMSET(newStatus, 0, sizeof(CertStatus)); InitOcspResponse(ocspResponse, newStatus, ocspRespBuf, result); OcspResponseDecode(ocspResponse); if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) result = OCSP_LOOKUP_FAIL; else { if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) { result = xstat2err(ocspResponse->status->status); if (LockMutex(&ocsp->ocspLock) != 0) result = BAD_MUTEX_E; else { if (certStatus != NULL) /* Replace existing certificate entry with updated */ XMEMCPY(certStatus, newStatus, sizeof(CertStatus)); else { /* Save new certificate entry */ certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, DYNAMIC_TYPE_OCSP_STATUS); if (certStatus != NULL) { XMEMCPY(certStatus, newStatus, sizeof(CertStatus)); certStatus->next = ocspe->status; ocspe->status = certStatus; ocspe->totalStatus++; } } UnLockMutex(&ocsp->ocspLock); } } else result = OCSP_LOOKUP_FAIL; } } else result = OCSP_LOOKUP_FAIL; XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER); #ifdef WOLFSSL_SMALL_STACK XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb) ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf); WOLFSSL_LEAVE("CheckCertOCSP", result); return result; }
int EmbedOcspLookup(void* ctx, const char* url, int urlSz, byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf) { SOCKET_T sfd = 0; word16 port; int ret = -1; #ifdef WOLFSSL_SMALL_STACK char* path; char* domainName; #else char path[80]; char domainName[80]; #endif #ifdef WOLFSSL_SMALL_STACK path = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (path == NULL) return -1; domainName = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (domainName == NULL) { XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); return -1; } #endif (void)ctx; if (ocspReqBuf == NULL || ocspReqSz == 0) { WOLFSSL_MSG("OCSP request is required for lookup"); } else if (ocspRespBuf == NULL) { WOLFSSL_MSG("Cannot save OCSP response"); } else if (decode_url(url, urlSz, domainName, path, &port) < 0) { WOLFSSL_MSG("Unable to decode OCSP URL"); } else { /* Note, the library uses the EmbedOcspRespFree() callback to * free this buffer. */ int httpBufSz = SCRATCH_BUFFER_SIZE; byte* httpBuf = (byte*)XMALLOC(httpBufSz, NULL, DYNAMIC_TYPE_OCSP); if (httpBuf == NULL) { WOLFSSL_MSG("Unable to create OCSP response buffer"); } else { httpBufSz = build_http_request(domainName, path, ocspReqSz, httpBuf, httpBufSz); if ((tcp_connect(&sfd, domainName, port) != 0) || (sfd <= 0)) { WOLFSSL_MSG("OCSP Responder connection failed"); } else if ((int)SEND_FUNCTION(sfd, (char*)httpBuf, httpBufSz, 0) != httpBufSz) { WOLFSSL_MSG("OCSP http request failed"); } else if ((int)SEND_FUNCTION(sfd, (char*)ocspReqBuf, ocspReqSz, 0) != ocspReqSz) { WOLFSSL_MSG("OCSP ocsp request failed"); } else { ret = process_http_response(sfd, ocspRespBuf, httpBuf, SCRATCH_BUFFER_SIZE); } CLOSE_FUNCTION(sfd); XFREE(httpBuf, NULL, DYNAMIC_TYPE_OCSP); } } #ifdef WOLFSSL_SMALL_STACK XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; }
/** Encrypt a symmetric key with ECC @param in The symmetric key you want to encrypt @param inlen The length of the key to encrypt (octets) @param out [out] The destination for the ciphertext @param outlen [in/out] The max size and resulting size of the ciphertext @param prng An active PRNG state @param wprng The index of the PRNG you wish to use @param hash The index of the hash you want to use @param key The ECC key you want to encrypt to @return CRYPT_OK if successful */ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, int hash, ecc_key *key) { unsigned char *pub_expt, *ecc_shared, *skey; ecc_key pubkey; unsigned long x, y, pubkeysize; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* check that wprng/cipher/hash are not invalid */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } if (inlen > hash_descriptor[hash].hashsize) { return CRYPT_INVALID_HASH; } /* make a random key and export the public copy */ if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) { return err; } pub_expt = XMALLOC(ECC_BUF_SIZE); ecc_shared = XMALLOC(ECC_BUF_SIZE); skey = XMALLOC(MAXBLOCKSIZE); if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { if (pub_expt != NULL) { XFREE(pub_expt); } if (ecc_shared != NULL) { XFREE(ecc_shared); } if (skey != NULL) { XFREE(skey); } ecc_free(&pubkey); return CRYPT_MEM; } pubkeysize = ECC_BUF_SIZE; if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) { ecc_free(&pubkey); goto LBL_ERR; } /* make random key */ x = ECC_BUF_SIZE; if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) { ecc_free(&pubkey); goto LBL_ERR; } ecc_free(&pubkey); y = MAXBLOCKSIZE; if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) { goto LBL_ERR; } /* Encrypt key */ for (x = 0; x < inlen; x++) { skey[x] ^= in[x]; } err = der_encode_sequence_multi(out, outlen, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID, LTC_ASN1_OCTET_STRING, pubkeysize, pub_expt, LTC_ASN1_OCTET_STRING, inlen, skey, LTC_ASN1_EOL, 0UL, NULL); LBL_ERR: #ifdef LTC_CLEAN_STACK /* clean up */ zeromem(pub_expt, ECC_BUF_SIZE); zeromem(ecc_shared, ECC_BUF_SIZE); zeromem(skey, MAXBLOCKSIZE); #endif XFREE(skey); XFREE(ecc_shared); XFREE(pub_expt); return err; }
/** Execute PKCS #5 v1 @param password The password (or key) @param password_len The length of the password (octet) @param salt The salt (or nonce) which is 8 octets long @param iteration_count The PKCS #5 v1 iteration count @param hash_idx The index of the hash desired @param out [out] The destination for this algorithm @param outlen [in/out] The max size and resulting size of the algorithm output @return CRYPT_OK if successful */ int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, const unsigned char *salt, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen) { int err; unsigned long x; hash_state *md; unsigned char *buf; LTC_ARGCHK(password != NULL); LTC_ARGCHK(salt != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* test hash IDX */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* allocate memory */ md = XMALLOC(sizeof(hash_state)); buf = XMALLOC(MAXBLOCKSIZE); if (md == NULL || buf == NULL) { if (md != NULL) { XFREE(md); } if (buf != NULL) { XFREE(buf); } return CRYPT_MEM; } /* hash initial password + salt */ if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].process(md, password, password_len)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].process(md, salt, 8)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) { goto LBL_ERR; } while (--iteration_count) { /* code goes here. */ x = MAXBLOCKSIZE; if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx].hashsize, buf, &x)) != CRYPT_OK) { goto LBL_ERR; } } /* copy upto outlen bytes */ for (x = 0; x < hash_descriptor[hash_idx].hashsize && x < *outlen; x++) { out[x] = buf[x]; } *outlen = x; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf, MAXBLOCKSIZE); zeromem(md, sizeof(hash_state)); #endif XFREE(buf); XFREE(md); return err; }
/** Terminate an HMAC session @param hmac The HMAC state @param out [out] The destination of the HMAC authentication tag @param outlen [in/out] The max size and resulting size of the HMAC authentication tag @return CRYPT_OK if successful */ int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen) { unsigned char *buf, *isha; unsigned long hashsize, i; int hash, err; LTC_ARGCHK(hmac != NULL); LTC_ARGCHK(out != NULL); /* test hash */ hash = hmac->hash; if((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } /* get the hash message digest size */ hashsize = hash_descriptor[hash].hashsize; /* allocate buffers */ buf = XMALLOC(HMAC_BLOCKSIZE); isha = XMALLOC(hashsize); if (buf == NULL || isha == NULL) { if (buf != NULL) { XFREE(buf); } if (isha != NULL) { XFREE(isha); } return CRYPT_MEM; } /* Get the hash of the first HMAC vector plus the data */ if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) { goto LBL_ERR; } /* Create the second HMAC vector vector for step (3) */ for(i=0; i < HMAC_BLOCKSIZE; i++) { buf[i] = hmac->key[i] ^ 0x5C; } /* Now calculate the "outer" hash for step (5), (6), and (7) */ if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash].process(&hmac->md, isha, hashsize)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash].done(&hmac->md, buf)) != CRYPT_OK) { goto LBL_ERR; } /* copy to output */ for (i = 0; i < hashsize && i < *outlen; i++) { out[i] = buf[i]; } *outlen = i; err = CRYPT_OK; LBL_ERR: XFREE(hmac->key); #ifdef LTC_CLEAN_STACK zeromem(isha, hashsize); zeromem(buf, hashsize); zeromem(hmac, sizeof(*hmac)); #endif XFREE(isha); XFREE(buf); return err; }
/** Sign a hash with DSA @param in The hash to sign @param inlen The length of the hash to sign @param r The "r" integer of the signature (caller must initialize with mp_init() first) @param s The "s" integer of the signature (caller must initialize with mp_init() first) @param prng An active PRNG state @param wprng The index of the PRNG desired @param key A private DSA key @return CRYPT_OK if successful */ int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, mp_int *r, mp_int *s, prng_state *prng, int wprng, dsa_key *key) { mp_int k, kinv, tmp; unsigned char *buf; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(r != NULL); LTC_ARGCHK(s != NULL); LTC_ARGCHK(key != NULL); if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } if (key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } /* check group order size */ if (key->qord >= MDSA_MAX_GROUP) { return CRYPT_INVALID_ARG; } buf = XMALLOC(MDSA_MAX_GROUP); if (buf == NULL) { return CRYPT_MEM; } /* Init our temps */ if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != MP_OKAY) { goto error; } retry: do { /* gen random k */ if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) { err = CRYPT_ERROR_READPRNG; goto LBL_ERR; } /* read k */ if ((err = mp_read_unsigned_bin(&k, buf, key->qord)) != MP_OKAY) { goto error; } /* k > 1 ? */ if (mp_cmp_d(&k, 1) != MP_GT) { goto retry; } /* test gcd */ if ((err = mp_gcd(&k, &key->q, &tmp)) != MP_OKAY) { goto error; } } while (mp_cmp_d(&tmp, 1) != MP_EQ); /* now find 1/k mod q */ if ((err = mp_invmod(&k, &key->q, &kinv)) != MP_OKAY) { goto error; } /* now find r = g^k mod p mod q */ if ((err = mp_exptmod(&key->g, &k, &key->p, r)) != MP_OKAY) { goto error; } if ((err = mp_mod(r, &key->q, r)) != MP_OKAY) { goto error; } if (mp_iszero(r) == MP_YES) { goto retry; } /* now find s = (in + xr)/k mod q */ if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; } if ((err = mp_mul(&key->x, r, s)) != MP_OKAY) { goto error; } if ((err = mp_add(s, &tmp, s)) != MP_OKAY) { goto error; } if ((err = mp_mulmod(s, &kinv, &key->q, s)) != MP_OKAY) { goto error; } if (mp_iszero(s) == MP_YES) { goto retry; } err = CRYPT_OK; goto LBL_ERR; error: err = mpi_to_ltc_error(err); LBL_ERR: mp_clear_multi(&k, &kinv, &tmp, NULL); #ifdef LTC_CLEAN_STACK zeromem(buf, MDSA_MAX_GROUP); #endif XFREE(buf); return err; }
int main(int argc, char *argv[]) { FILE *inFile = NULL, *outFile = NULL; char inBuf[8192]; char outFileName[PATH_MAX]; PRIVATE int c = 0, i, ret; #ifndef DEBUG struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = 0; setrlimit( RLIMIT_CORE, &rlim ); #endif /* setup config */ config = ( Config_t * )XMALLOC( sizeof( Config_t ) ); XMEMSET( config, 0, sizeof( Config_t ) ); /* force mode to forground */ config->mode = MODE_INTERACTIVE; /* store current pid */ config->cur_pid = getpid(); /* get real uid and gid in prep for priv drop */ config->gid = getgid(); config->uid = getuid(); while (1) { int this_option_optind = optind ? optind : 1; #ifdef HAVE_GETOPT_LONG int option_index = 0; static struct option long_options[] = { {"chain", no_argument, 0, 'C' }, {"cluster", no_argument, 0, 'c' }, {"greedy", no_argument, 0, 'g' }, {"version", no_argument, 0, 'v' }, {"debug", required_argument, 0, 'd' }, {"help", no_argument, 0, 'h' }, {"cnum", required_argument, 0, 'n' }, {"templates", required_argument, 0, 't' }, {"write", required_argument, 0, 'w' }, {"match", required_argument, 0, 'm' }, {"matchfile", required_argument, 0, 'M' }, {"line", required_argument, 0, 'l' }, {"linefile", required_argument, 0, 'L' }, {0, no_argument, 0, 0} }; c = getopt_long(argc, argv, "vd:hn:t:w:cCgm:M:l:L:", long_options, &option_index); #else c = getopt( argc, argv, "vd:htn::w:cCgm:M:l:L:" ); #endif if (c EQ -1) break; switch (c) { case 'v': /* show the version */ print_version(); return( EXIT_SUCCESS ); case 'c': /* enable argument clustering */ config->cluster = TRUE; break; case 'C': /* enable log chaining */ config->cluster = TRUE; config->chain = TRUE; break; case 'd': /* show debig info */ config->debug = atoi( optarg ); break; case 'g': /* ignore quotes */ config->greedy = TRUE; break; case 'n': /* override default cluster count */ config->clusterDepth = atoi( optarg ); break; case 't': /* load template file */ if ( loadTemplateFile( optarg ) != TRUE ) { fprintf( stderr, "ERR - Problem while loading template file\n" ); return( EXIT_FAILURE ); } break; case 'h': /* show help info */ print_help(); return( EXIT_SUCCESS ); case 'w': /* save templates to file */ if ( ( config->outFile_st = fopen( optarg, "w" ) ) EQ NULL ) { fprintf( stderr, "ERR - Unable to open template file for write [%s]\n", optarg ); return( EXIT_FAILURE ); } break; case 'M': /* load match templates from file */ config->match = loadMatchTemplates( optarg ); break; case 'm': /* add template to match list */ config->match = addMatchTemplate( optarg ); break; case 'L': /* load match lines from file and convert to templates */ config->match = loadMatchLines( optarg ); break; case 'l': /* convert match line and add as template */ config->match = addMatchLine( optarg ); break; default: fprintf( stderr, "Unknown option code [0%o]\n", c); } } /* override cluster depth */ if ( ( config->clusterDepth <= 0 ) | ( config->clusterDepth > 10000 ) ) config->clusterDepth = MAX_ARGS_IN_FIELD; /* check dirs and files for danger */ if ( time( &config->current_time ) EQ -1 ) { display( LOG_ERR, "Unable to get current time" ); /* cleanup buffers */ cleanup(); return( EXIT_FAILURE ); } /* initialize program wide config options */ config->hostname = (char *)XMALLOC( MAXHOSTNAMELEN+1 ); /* get processor hostname */ if ( gethostname( config->hostname, MAXHOSTNAMELEN ) != 0 ) { display( LOG_ERR, "Unable to get hostname" ); strcpy( config->hostname, "unknown" ); } config->cur_pid = getpid(); /* setup current time updater */ signal( SIGALRM, ctime_prog ); alarm( ALARM_TIMER ); /* * get to work */ /* process all the files */ while (optind < argc) { processFile( argv[optind++] ); } if ( config->match ) { /* XXX should print match metrict */ } else { /* print the templates we have found */ showTemplates(); } /* * finished with the work */ cleanup(); return( EXIT_SUCCESS ); }
/** Create a DSA key @param prng An active PRNG state @param wprng The index of the PRNG desired @param group_size Size of the multiplicative group (octets) @param modulus_size Size of the modulus (octets) @param key [out] Where to store the created key @return CRYPT_OK if successful, upon error this function will free all allocated memory */ int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) { void *tmp, *tmp2; int err, res; unsigned char *buf; LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* check prng */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } /* check size */ if (group_size >= LTC_MDSA_MAX_GROUP || group_size <= 15 || group_size >= modulus_size || (modulus_size - group_size) >= LTC_MDSA_DELTA) { return CRYPT_INVALID_ARG; } /* allocate ram */ buf = XMALLOC(LTC_MDSA_DELTA); if (buf == NULL) { return CRYPT_MEM; } /* init mp_ints */ if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) { XFREE(buf); return err; } /* make our prime q */ if ((err = rand_prime(key->q, group_size, prng, wprng)) != CRYPT_OK) { goto error; } /* double q */ if ((err = mp_add(key->q, key->q, tmp)) != CRYPT_OK) { goto error; } /* now make a random string and multply it against q */ if (prng_descriptor[wprng]->read(buf+1, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) { err = CRYPT_ERROR_READPRNG; goto error; } /* force magnitude */ buf[0] |= 0xC0; /* force even */ buf[modulus_size - group_size - 1] &= ~1; if ((err = mp_read_unsigned_bin(tmp2, buf, modulus_size - group_size)) != CRYPT_OK) { goto error; } if ((err = mp_mul(key->q, tmp2, key->p)) != CRYPT_OK) { goto error; } if ((err = mp_add_d(key->p, 1, key->p)) != CRYPT_OK) { goto error; } /* now loop until p is prime */ for (;;) { if ((err = mp_prime_is_prime(key->p, 8, &res)) != CRYPT_OK) { goto error; } if (res == LTC_MP_YES) break; /* add 2q to p and 2 to tmp2 */ if ((err = mp_add(tmp, key->p, key->p)) != CRYPT_OK) { goto error; } if ((err = mp_add_d(tmp2, 2, tmp2)) != CRYPT_OK) { goto error; } } /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */ mp_set(key->g, 1); do { if ((err = mp_add_d(key->g, 1, key->g)) != CRYPT_OK) { goto error; } if ((err = mp_exptmod(key->g, tmp2, key->p, tmp)) != CRYPT_OK) { goto error; } } while (mp_cmp_d(tmp, 1) == LTC_MP_EQ); /* at this point tmp generates a group of order q mod p */ mp_exch(tmp, key->g); /* so now we have our DH structure, generator g, order q, modulus p Now we need a random exponent [mod q] and it's power g^x mod p */ do { if (prng_descriptor[wprng]->read(buf, group_size, prng) != (unsigned long)group_size) { err = CRYPT_ERROR_READPRNG; goto error; } if ((err = mp_read_unsigned_bin(key->x, buf, group_size)) != CRYPT_OK) { goto error; } } while (mp_cmp_d(key->x, 1) != LTC_MP_GT); if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto error; } key->type = PK_PRIVATE; key->qord = group_size; #ifdef LTC_CLEAN_STACK zeromem(buf, LTC_MDSA_DELTA); #endif err = CRYPT_OK; goto done; error: mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL); done: mp_clear_multi(tmp, tmp2, NULL); XFREE(buf); return err; }
int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, buffer* responseBuffer) { OcspEntry* entry = NULL; CertStatus* status = NULL; byte* request = NULL; int requestSz = 2048; byte* response = NULL; const char* url = NULL; int urlSz = 0; int ret = -1; #ifdef WOLFSSL_SMALL_STACK CertStatus* newStatus; OcspResponse* ocspResponse; #else CertStatus newStatus[1]; OcspResponse ocspResponse[1]; #endif WOLFSSL_ENTER("CheckOcspRequest"); if (responseBuffer) { responseBuffer->buffer = NULL; responseBuffer->length = 0; } ret = GetOcspEntry(ocsp, ocspRequest, &entry); if (ret != 0) return ret; ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer); if (ret != OCSP_INVALID_STATUS) return ret; if (ocsp->cm->ocspUseOverrideURL) { url = ocsp->cm->ocspOverrideURL; if (url != NULL && url[0] != '\0') urlSz = (int)XSTRLEN(url); else return OCSP_NEED_URL; } else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) { url = (const char *)ocspRequest->url; urlSz = ocspRequest->urlSz; } else { /* cert doesn't have extAuthInfo, assuming CERT_GOOD */ return 0; } request = (byte*)XMALLOC(requestSz, NULL, DYNAMIC_TYPE_OCSP); if (request == NULL) { WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); return MEMORY_ERROR; } #ifdef WOLFSSL_SMALL_STACK newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, DYNAMIC_TYPE_TMP_BUFFER); ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (newStatus == NULL || ocspResponse == NULL) { if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(request, NULL, DYNAMIC_TYPE_OCSP); WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); return MEMORY_E; } #endif requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); if (ocsp->cm->ocspIOCb) ret = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, request, requestSz, &response); if (ret >= 0 && response) { XMEMSET(newStatus, 0, sizeof(CertStatus)); InitOcspResponse(ocspResponse, newStatus, response, ret); OcspResponseDecode(ocspResponse, ocsp->cm); if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) ret = OCSP_LOOKUP_FAIL; else { if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) { if (responseBuffer) { responseBuffer->buffer = (byte*)XMALLOC(ret, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (responseBuffer->buffer) { responseBuffer->length = ret; XMEMCPY(responseBuffer->buffer, response, ret); } } ret = xstat2err(ocspResponse->status->status); if (LockMutex(&ocsp->ocspLock) != 0) ret = BAD_MUTEX_E; else { if (status != NULL) { if (status->rawOcspResponse) XFREE(status->rawOcspResponse, NULL, DYNAMIC_TYPE_OCSP_STATUS); /* Replace existing certificate entry with updated */ XMEMCPY(status, newStatus, sizeof(CertStatus)); } else { /* Save new certificate entry */ status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, DYNAMIC_TYPE_OCSP_STATUS); if (status != NULL) { XMEMCPY(status, newStatus, sizeof(CertStatus)); status->next = entry->status; entry->status = status; entry->totalStatus++; } } if (status && responseBuffer && responseBuffer->buffer) { status->rawOcspResponse = (byte*)XMALLOC( responseBuffer->length, NULL, DYNAMIC_TYPE_OCSP_STATUS); if (status->rawOcspResponse) { status->rawOcspResponseSz = responseBuffer->length; XMEMCPY(status->rawOcspResponse, responseBuffer->buffer, responseBuffer->length); } } UnLockMutex(&ocsp->ocspLock); } } else ret = OCSP_LOOKUP_FAIL; } } else ret = OCSP_LOOKUP_FAIL; #ifdef WOLFSSL_SMALL_STACK XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif if (response != NULL && ocsp->cm->ocspRespFreeCb) ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response); WOLFSSL_LEAVE("CheckOcspRequest", ret); return ret; }
int ecc_dp_set_by_oid(ltc_ecc_set_type *dp, unsigned long *oid, unsigned long oidsize) { int i; unsigned long len; for(i=0; ltc_ecc_sets[i].size != 0; i++) { if ((oidsize == ltc_ecc_sets[i].oid.OIDlen) && (XMEM_NEQ(oid, ltc_ecc_sets[i].oid.OID, sizeof(unsigned long) * ltc_ecc_sets[i].oid.OIDlen) == 0)) { break; } } if (ltc_ecc_sets[i].size == 0) return CRYPT_INVALID_ARG; /* not found */ /* a */ len = (unsigned long)strlen(ltc_ecc_sets[i].A); if ((dp->A = XMALLOC(1+len)) == NULL) goto cleanup1; strncpy(dp->A, ltc_ecc_sets[i].A, 1+len); /* b */ len = (unsigned long)strlen(ltc_ecc_sets[i].B); if ((dp->B = XMALLOC(1+len)) == NULL) goto cleanup2; strncpy(dp->B, ltc_ecc_sets[i].B, 1+len); /* order */ len = (unsigned long)strlen(ltc_ecc_sets[i].order); if ((dp->order = XMALLOC(1+len)) == NULL) goto cleanup3; strncpy(dp->order, ltc_ecc_sets[i].order, 1+len); /* prime */ len = (unsigned long)strlen(ltc_ecc_sets[i].prime); if ((dp->prime = XMALLOC(1+len)) == NULL) goto cleanup4; strncpy(dp->prime, ltc_ecc_sets[i].prime, 1+len); /* gx */ len = (unsigned long)strlen(ltc_ecc_sets[i].Gx); if ((dp->Gx = XMALLOC(1+len)) == NULL) goto cleanup5; strncpy(dp->Gx, ltc_ecc_sets[i].Gx, 1+len); /* gy */ len = (unsigned long)strlen(ltc_ecc_sets[i].Gy); if ((dp->Gy = XMALLOC(1+len)) == NULL) goto cleanup6; strncpy(dp->Gy, ltc_ecc_sets[i].Gy, 1+len); /* cofactor & size */ dp->cofactor = ltc_ecc_sets[i].cofactor; dp->size = ltc_ecc_sets[i].size; /* name */ len = (unsigned long)strlen(ltc_ecc_sets[i].name); if ((dp->name = XMALLOC(1+len)) == NULL) goto cleanup7; strncpy(dp->name, ltc_ecc_sets[i].name, 1+len); /* oid */ dp->oid.OIDlen = ltc_ecc_sets[i].oid.OIDlen; XMEMCPY(dp->oid.OID, ltc_ecc_sets[i].oid.OID, dp->oid.OIDlen * sizeof(dp->oid.OID[0])); /* done - success */ return CRYPT_OK; cleanup7: XFREE(dp->Gy); cleanup6: XFREE(dp->Gx); cleanup5: XFREE(dp->prime); cleanup4: XFREE(dp->order); cleanup3: XFREE(dp->B); cleanup2: XFREE(dp->A); cleanup1: return CRYPT_MEM; }
/* HMAC-KDF with hash type, optional salt and info, return 0 on success */ int wc_HKDF(int type, const byte* inKey, word32 inKeySz, const byte* salt, word32 saltSz, const byte* info, word32 infoSz, byte* out, word32 outSz) { Hmac myHmac; #ifdef WOLFSSL_SMALL_STACK byte* tmp; byte* prk; #else byte tmp[MAX_DIGEST_SIZE]; /* localSalt helper and T */ byte prk[MAX_DIGEST_SIZE]; #endif const byte* localSalt; /* either points to user input or tmp */ int hashSz = GetHashSizeByType(type); word32 outIdx = 0; byte n = 0x1; int ret; if (hashSz < 0) return BAD_FUNC_ARG; #ifdef WOLFSSL_SMALL_STACK tmp = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) return MEMORY_E; prk = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (prk == NULL) { XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } #endif localSalt = salt; if (localSalt == NULL) { XMEMSET(tmp, 0, hashSz); localSalt = tmp; saltSz = hashSz; } do { ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); if (ret != 0) break; ret = wc_HmacUpdate(&myHmac, inKey, inKeySz); if (ret != 0) break; ret = wc_HmacFinal(&myHmac, prk); } while (0); if (ret == 0) { while (outIdx < outSz) { int tmpSz = (n == 1) ? 0 : hashSz; word32 left = outSz - outIdx; ret = wc_HmacSetKey(&myHmac, type, prk, hashSz); if (ret != 0) break; ret = wc_HmacUpdate(&myHmac, tmp, tmpSz); if (ret != 0) break; ret = wc_HmacUpdate(&myHmac, info, infoSz); if (ret != 0) break; ret = wc_HmacUpdate(&myHmac, &n, 1); if (ret != 0) break; ret = wc_HmacFinal(&myHmac, tmp); if (ret != 0) break; left = min(left, (word32)hashSz); XMEMCPY(out+outIdx, tmp, left); outIdx += hashSz; n++; } } #ifdef WOLFSSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(prk, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; }
static int te_zebra_read_link (int command, struct zclient *zclient, zebra_size_t length) { struct stream *s; struct zapi_te_link link; s = zclient->ibuf; zapi_te_link_read(s, &link); switch(command) { case ZEBRA_TE_LINK_ADD: { TE_LINK *pTeLink; COMPONENT_LINK *pComponentLink; int ComponentLinksNumber = 1, i, j; PATRICIA_PARAMS params; if ((pTeLink = (TE_LINK *) XMALLOC (MTYPE_TE, sizeof (TE_LINK))) == NULL) { zlog_err ("\ncannnot allocate memory"); return; } pTeLink->component_links = NULL; pTeLink->te_link_id = link->linkid; pTeLink->type = PSC_PATH; pTeLink->te_link_properties.TeMetric = link->metric; pTeLink->te_link_properties.color_mask = link->color_mask; pTeLink->te_link_properties.MaxLspBW = link->max_lsp_bw; pTeLink->te_link_properties.MaxReservableBW = link->max_res_bw; for (j = 0; j < 8; j++) pTeLink->te_link_properties.ReservableBW[j] = 0; for (i = 0; i < ComponentLinksNumber; i++) { if ((pComponentLink = new_component_link ()) == NULL) { zlog_err ("\ncan initiate component link %s %d", __FILE__, __LINE__); return; } params.key_size = sizeof (FRR_LABEL_ENTRY); params.info_size = 0; if (patricia_tree_init (&pComponentLink->ProtectionTree, ¶ms) != E_OK) { zlog_err ("\ncannot initiate patricia tree (per SM) for FRR"); return; } params.key_size = sizeof (PSB_KEY); params.info_size = 0; if (patricia_tree_init (&pComponentLink->IngressProtectionTree, ¶ms) != E_OK) { zlog_err ("\ncannot initiate patricia tree (per SM) for FRR"); return; } pComponentLink->next = pTeLink->component_links; pTeLink->component_links = pComponentLink; pComponentLink->oifIndex = link->ifindex; /*pTeLink->te_link_id */ for (j = 0; j < 8; j++) { pComponentLink->ReservableBW[j] = link->reservable_bw[j]; pComponentLink->ConfiguredReservableBW[j] = link->reservable_bw[j]; pTeLink->te_link_properties.ReservableBW[j] += pComponentLink->ReservableBW[j]; } } if (rdb_add_te_link (pTeLink) != E_OK) { zlog_err ("\nCannot delete TE link"); } } break; case ZEBRA_TE_LINK_DELETE: if (rdb_del_te_link (link->linkid) != E_OK) { zlog_err ("\nCannot delete TE link"); } break; case ZEBRA_TE_LINK_UPDATE: if (rdb_local_link_status_change (link->linkid, link->status) != E_OK) { zlog_err ("\nCannot set TE link down"); } break; } }
int main(int argc, char **argv) { data d; glam2_aln *alns; int r; prog_name = "glam2"; /* for error messages */ getargs(&d.a, argc, argv); init(&d); fputs("GLAM2: Gapped Local Alignment of Motifs\nVersion " #include "glam2_version.h" "\n\n", d.out); printargs(d.out, argc, argv); print_misc_info(d.out, &d); putc('\n', d.out); XMALLOC(alns, d.a.runs); for (r = 0; r < d.a.runs; ++r) { glam2_aln *aln = &alns[r]; if (!d.a.quiet) { fprintf(stderr, "Run %d... ", r+1); fflush(stderr); } aln_init(aln, d.seqs.seqnum, d.a.max_width, d.alph.size); d.sm.underflow_flag = 1; /* do we care about underflow in start_aln? */ start_aln(aln, &d); optimise_aln(aln, &d); if (d.sm.underflow_flag < (d.a.algorithm == 2 ? DBL_EPSILON : DBL_MIN)) fprintf(stderr, "%s: accuracy loss due to numeric underflow (%g)\nIf the alignment looks suspect, try rerunning with higher -u, or maybe lower -b\n", prog_name, d.sm.underflow_flag); if (d.a.profile) print_aln_info(d.out, aln, &d); } if (!d.a.quiet) putc('\n', stderr); SORT(alns, d.a.runs, aln_cmp); if (!d.a.profile) print_alns(d.out, alns, &d); xfclose(d.out); // close text output file // Create the HTML output and MEME format output char *glam2html, *glam2psfm, *command; int command_length, command_ret; // create the paths to the programs glam2html = make_path_to_file(get_meme_bin_dir(), "glam2html"); glam2psfm = make_path_to_file(get_meme_bin_dir(), "glam2psfm"); // allocate memory for the command command_length = strlen(glam2html) + strlen(d.txt_filename) + strlen(d.html_filename) + 50; command = xmalloc(command_length); // run glam2html sprintf(command, "%s < %s > %s", glam2html, d.txt_filename, d.html_filename); if ((command_ret = system(command)) != 0) { report_external_failure("glam2html", command_ret); fprintf(stderr, "Warning: failed to convert output to HTML!\n"); } // run glam2psfm sprintf(command, "%s < %s > %s", glam2psfm, d.txt_filename, d.psfm_filename); if ((command_ret = system(command)) != 0) { report_external_failure("glam2psfm", command_ret); fprintf(stderr, "Warning: failed to convert output to MEME format motif!\n"); } free(command); free(glam2psfm); free(glam2html); return 0; }
/** Decrypt an ECC encrypted key @param in The ciphertext @param inlen The length of the ciphertext (octets) @param out [out] The plaintext @param outlen [in/out] The max size and resulting size of the plaintext @param key The corresponding private ECC key @return CRYPT_OK if successful */ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, ecc_key *key) { unsigned char *ecc_shared, *skey, *pub_expt; unsigned long x, y, hashOID[32]; int hash, err; ecc_key pubkey; ltc_asn1_list decode[3]; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* right key type? */ if (key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } /* decode to find out hash */ LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) { return err; } for (hash = 0; hash_descriptor[hash].name != NULL && (hash_descriptor[hash].OIDlen != decode[0].size || memcmp(hash_descriptor[hash].OID, hashOID, sizeof(unsigned long)*decode[0].size)); hash++); if (hash_descriptor[hash].name == NULL) { return CRYPT_INVALID_PACKET; } /* we now have the hash! */ /* allocate memory */ pub_expt = XMALLOC(ECC_BUF_SIZE); ecc_shared = XMALLOC(ECC_BUF_SIZE); skey = XMALLOC(MAXBLOCKSIZE); if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { if (pub_expt != NULL) { XFREE(pub_expt); } if (ecc_shared != NULL) { XFREE(ecc_shared); } if (skey != NULL) { XFREE(skey); } return CRYPT_MEM; } LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE); LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); /* read the structure in now */ if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { goto LBL_ERR; } /* import ECC key from packet */ if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) { goto LBL_ERR; } /* make shared key */ x = ECC_BUF_SIZE; if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) { ecc_free(&pubkey); goto LBL_ERR; } ecc_free(&pubkey); y = MAXBLOCKSIZE; if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) { goto LBL_ERR; } /* ensure the hash of the shared secret is at least as big as the encrypt itself */ if (decode[2].size > y) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } /* avoid buffer overflow */ if (*outlen < decode[2].size) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* Decrypt the key */ for (x = 0; x < decode[2].size; x++) { out[x] = skey[x] ^ ecc_shared[x]; } *outlen = x; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(pub_expt, ECC_BUF_SIZE); zeromem(ecc_shared, ECC_BUF_SIZE); zeromem(skey, MAXBLOCKSIZE); #endif XFREE(pub_expt); XFREE(ecc_shared); XFREE(skey); return err; }
static int interface_list_ioctl (int af) { int ret; int sock; #define IFNUM_BASE 32 struct lifnum lifn; int ifnum; struct lifreq *lifreq; struct lifconf lifconf; struct interface *ifp; int n; int save_errno; size_t needed, lastneeded = 0; char *buf = NULL; if (zserv_privs.change(ZPRIVS_RAISE)) zlog (NULL, LOG_ERR, "Can't raise privileges"); sock = socket (af, SOCK_DGRAM, 0); if (sock < 0) { zlog_warn ("Can't make %s socket stream: %s", (af == AF_INET ? "AF_INET" : "AF_INET6"), safe_strerror (errno)); if (zserv_privs.change(ZPRIVS_LOWER)) zlog (NULL, LOG_ERR, "Can't lower privileges"); return -1; } calculate_lifc_len: /* must hold privileges to enter here */ lifn.lifn_family = af; lifn.lifn_flags = LIFC_NOXMIT; /* we want NOXMIT interfaces too */ ret = ioctl (sock, SIOCGLIFNUM, &lifn); save_errno = errno; if (zserv_privs.change(ZPRIVS_LOWER)) zlog (NULL, LOG_ERR, "Can't lower privileges"); if (ret < 0) { zlog_warn ("interface_list_ioctl: SIOCGLIFNUM failed %s", safe_strerror (save_errno)); close (sock); return -1; } ifnum = lifn.lifn_count; /* * When calculating the buffer size needed, add a small number * of interfaces to those we counted. We do this to capture * the interface status of potential interfaces which may have * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF. */ needed = (ifnum + 4) * sizeof (struct lifreq); if (needed > lastneeded || needed < lastneeded / 2) { if (buf != NULL) XFREE (MTYPE_TMP, buf); if ((buf = XMALLOC (MTYPE_TMP, needed)) == NULL) { zlog_warn ("interface_list_ioctl: malloc failed"); close (sock); return -1; } } lastneeded = needed; lifconf.lifc_family = af; lifconf.lifc_flags = LIFC_NOXMIT; lifconf.lifc_len = needed; lifconf.lifc_buf = buf; if (zserv_privs.change(ZPRIVS_RAISE)) zlog (NULL, LOG_ERR, "Can't raise privileges"); ret = ioctl (sock, SIOCGLIFCONF, &lifconf); if (ret < 0) { if (errno == EINVAL) goto calculate_lifc_len; /* deliberately hold privileges */ zlog_warn ("SIOCGLIFCONF: %s", safe_strerror (errno)); if (zserv_privs.change(ZPRIVS_LOWER)) zlog (NULL, LOG_ERR, "Can't lower privileges"); goto end; } if (zserv_privs.change(ZPRIVS_LOWER)) zlog (NULL, LOG_ERR, "Can't lower privileges"); /* Allocate interface. */ lifreq = lifconf.lifc_req; for (n = 0; n < lifconf.lifc_len; n += sizeof (struct lifreq)) { /* we treat Solaris logical interfaces as addresses, because that is * how PF_ROUTE on Solaris treats them. Hence we can not directly use * the lifreq_name to get the ifp. We need to normalise the name * before attempting get. * * Solaris logical interface names are in the form of: * <interface name>:<logical interface id> */ unsigned int normallen = 0; uint64_t lifflags; /* We should exclude ~IFF_UP interfaces, as we'll find out about them * coming up later through RTM_NEWADDR message on the route socket. */ if (if_get_flags_direct (lifreq->lifr_name, &lifflags, lifreq->lifr_addr.ss_family) || !CHECK_FLAG (lifflags, IFF_UP)) { lifreq++; continue; } /* Find the normalised name */ while ( (normallen < sizeof(lifreq->lifr_name)) && ( *(lifreq->lifr_name + normallen) != '\0') && ( *(lifreq->lifr_name + normallen) != ':') ) normallen++; ifp = if_get_by_name_len(lifreq->lifr_name, normallen); if (lifreq->lifr_addr.ss_family == AF_INET) ifp->flags |= IFF_IPV4; if (lifreq->lifr_addr.ss_family == AF_INET6) { #ifdef HAVE_IPV6 ifp->flags |= IFF_IPV6; #else lifreq++; continue; #endif /* HAVE_IPV6 */ } if_add_update (ifp); interface_info_ioctl (ifp); /* If a logical interface pass the full name so it can be * as a label on the address */ if ( *(lifreq->lifr_name + normallen) != '\0') if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr, lifreq->lifr_name); else if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr, NULL); /* Poke the interface flags. Lets IFF_UP mangling kick in */ if_flags_update (ifp, ifp->flags); lifreq++; } end: close (sock); XFREE (MTYPE_TMP, lifconf.lifc_buf); return ret; }
/** Perform PKCS #1 MGF1 (internal) @param seed The seed for MGF1 @param seedlen The length of the seed @param hash_idx The index of the hash desired @param mask [out] The destination @param masklen The length of the mask desired @return CRYPT_OK if successful */ int pkcs_1_mgf1(const unsigned char *seed, unsigned long seedlen, int hash_idx, unsigned char *mask, unsigned long masklen) { unsigned long hLen, x; ulong32 counter; int err; hash_state *md; unsigned char *buf; LTC_ARGCHK(seed != NULL); LTC_ARGCHK(mask != NULL); /* ensure valid hash */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* get hash output size */ hLen = hash_descriptor[hash_idx].hashsize; /* allocate memory */ md = XMALLOC(sizeof(hash_state)); buf = XMALLOC(hLen); if (md == NULL || buf == NULL) { if (md != NULL) { XFREE(md); } if (buf != NULL) { XFREE(buf); } return CRYPT_MEM; } /* start counter */ counter = 0; while (masklen > 0) { /* handle counter */ STORE32H(counter, buf); ++counter; /* get hash of seed || counter */ if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].process(md, seed, seedlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].process(md, buf, 4)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) { goto LBL_ERR; } /* store it */ for (x = 0; x < hLen && masklen > 0; x++, masklen--) { *mask++ = buf[x]; } } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf, hLen); zeromem(md, sizeof(hash_state)); #endif XFREE(buf); XFREE(md); return err; }
/** f9 a file @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param fname The name of the file you wish to f9 @param out [out] Where the authentication tag is to be stored @param outlen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled */ int f9_file(int cipher, const unsigned char *key, unsigned long keylen, const char *fname, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE LTC_UNUSED_PARAM(cipher); LTC_UNUSED_PARAM(key); LTC_UNUSED_PARAM(keylen); LTC_UNUSED_PARAM(fname); LTC_UNUSED_PARAM(out); LTC_UNUSED_PARAM(outlen); return CRYPT_NOP; #else size_t x; int err; f9_state f9; FILE *in; unsigned char *buf; LTC_ARGCHK(key != NULL); LTC_ARGCHK(fname != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { return CRYPT_MEM; } if ((err = f9_init(&f9, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } in = fopen(fname, "rb"); if (in == NULL) { err = CRYPT_FILE_NOTFOUND; goto LBL_ERR; } do { x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); if ((err = f9_process(&f9, buf, (unsigned long)x)) != CRYPT_OK) { fclose(in); goto LBL_CLEANBUF; } } while (x == LTC_FILE_READ_BUFSIZE); if (fclose(in) != 0) { err = CRYPT_ERROR; goto LBL_CLEANBUF; } err = f9_done(&f9, out, outlen); LBL_CLEANBUF: zeromem(buf, LTC_FILE_READ_BUFSIZE); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&f9, sizeof(f9_state)); #endif XFREE(buf); return err; #endif }
/** Initialize an HMAC context. @param hmac The HMAC state @param hash The index of the hash you want to use @param key The secret key @param keylen The length of the secret key (octets) @return CRYPT_OK if successful */ int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen) { unsigned char *buf; unsigned long hashsize; unsigned long i, z; int err; LTC_ARGCHK(hmac != NULL); LTC_ARGCHK(key != NULL); /* valid hash? */ if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } hmac->hash = hash; hashsize = hash_descriptor[hash].hashsize; /* valid key length? */ if (keylen == 0) { return CRYPT_INVALID_KEYSIZE; } /* allocate ram for buf */ buf = XMALLOC(HMAC_BLOCKSIZE); if (buf == NULL) { return CRYPT_MEM; } /* allocate memory for key */ hmac->key = XMALLOC(HMAC_BLOCKSIZE); if (hmac->key == NULL) { XFREE(buf); return CRYPT_MEM; } /* (1) make sure we have a large enough key */ if(keylen > HMAC_BLOCKSIZE) { z = HMAC_BLOCKSIZE; if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) { goto LBL_ERR; } if(hashsize < HMAC_BLOCKSIZE) { zeromem((hmac->key) + hashsize, (size_t)(HMAC_BLOCKSIZE - hashsize)); } keylen = hashsize; } else { XMEMCPY(hmac->key, key, (size_t)keylen); if(keylen < HMAC_BLOCKSIZE) { zeromem((hmac->key) + keylen, (size_t)(HMAC_BLOCKSIZE - keylen)); } } /* Create the initial vector for step (3) */ for(i=0; i < HMAC_BLOCKSIZE; i++) { buf[i] = hmac->key[i] ^ 0x36; } /* Pre-pend that to the hash data */ if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE)) != CRYPT_OK) { goto LBL_ERR; } goto done; LBL_ERR: /* free the key since we failed */ XFREE(hmac->key); done: #ifdef LTC_CLEAN_STACK zeromem(buf, HMAC_BLOCKSIZE); #endif XFREE(buf); return err; }
/* Load CRL File of type, SSL_SUCCESS on ok */ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) { int ret = SSL_SUCCESS; const byte* myBuffer = buff; /* if DER ok, otherwise switch */ DerBuffer* der = NULL; #ifdef WOLFSSL_SMALL_STACK DecodedCRL* dcrl; #else DecodedCRL dcrl[1]; #endif WOLFSSL_ENTER("BufferLoadCRL"); if (crl == NULL || buff == NULL || sz == 0) return BAD_FUNC_ARG; if (type == SSL_FILETYPE_PEM) { int eccKey = 0; /* not used */ EncryptedInfo info; info.ctx = NULL; ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey); if (ret == 0) { myBuffer = der->buffer; sz = der->length; } else { WOLFSSL_MSG("Pem to Der failed"); FreeDer(&der); return -1; } } #ifdef WOLFSSL_SMALL_STACK dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (dcrl == NULL) { FreeDer(&der); return MEMORY_E; } #endif InitDecodedCRL(dcrl, crl->heap); ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm); if (ret != 0) { WOLFSSL_MSG("ParseCRL error"); } else { ret = AddCRL(crl, dcrl); if (ret != 0) { WOLFSSL_MSG("AddCRL error"); } } FreeDecodedCRL(dcrl); #ifdef WOLFSSL_SMALL_STACK XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif FreeDer(&der); return ret ? ret : SSL_SUCCESS; /* convert 0 to SSL_SUCCESS */ }
/* * This is the parent kcgi process. * It spins on input from the child until all fields have been received. * These fields are sent from the child's output() function. * Each input field consists of the data and its validation state. * We build up the kpair arrays here with this data, then assign the * kpairs into named buckets. */ enum kcgi_err kworker_parent(int fd, struct kreq *r, int eofok) { struct kpair kp; struct kpair *kpp; enum krequ requ; enum input type; int rc; enum kcgi_err ke; size_t i, dgsz; /* Pointers freed at "out" label. */ memset(&kp, 0, sizeof(struct kpair)); /* * First read all of our parsed parameters. * Each parsed parameter is handled a little differently. * This list will end with META__MAX. */ if (fullread(fd, &r->reqsz, sizeof(size_t), 0, &ke) < 0) { XWARNX("failed to read request header size"); goto out; } r->reqs = XCALLOC(r->reqsz, sizeof(struct khead)); if (NULL == r->reqs) { ke = KCGI_ENOMEM; goto out; } for (i = 0; i < r->reqsz; i++) { if (fullread(fd, &requ, sizeof(enum krequ), 0, &ke) < 0) { XWARNX("failed to read request identifier"); goto out; } if (KCGI_OK != (ke = fullreadword(fd, &r->reqs[i].key))) { XWARNX("failed to read request key"); goto out; } if (KCGI_OK != (ke = fullreadword(fd, &r->reqs[i].val))) { XWARNX("failed to read request value"); goto out; } if (requ != KREQU__MAX) r->reqmap[requ] = &r->reqs[i]; } if (fullread(fd, &r->method, sizeof(enum kmethod), 0, &ke) < 0) { XWARNX("failed to read request method"); goto out; } else if (fullread(fd, &r->auth, sizeof(enum kauth), 0, &ke) < 0) { XWARNX("failed to read authorisation type"); goto out; } else if (KCGI_OK != (ke = kworker_auth_parent(fd, &r->rawauth))) { XWARNX("failed to read raw authorisation"); goto out; } else if (fullread(fd, &r->scheme, sizeof(enum kscheme), 0, &ke) < 0) { XWARNX("failed to read scheme"); goto out; } else if (KCGI_OK != (ke = fullreadword(fd, &r->remote))) { XWARNX("failed to read remote"); goto out; } else if (KCGI_OK != (ke = fullreadword(fd, &r->fullpath))) { XWARNX("failed to read fullpath"); goto out; } else if (KCGI_OK != (ke = fullreadword(fd, &r->suffix))) { XWARNX("failed to read suffix"); goto out; } else if (KCGI_OK != (ke = fullreadword(fd, &r->pagename))) { XWARNX("failed to read page part"); goto out; } else if (KCGI_OK != (ke = fullreadword(fd, &r->path))) { XWARNX("failed to read path part"); goto out; } else if (KCGI_OK != (ke = fullreadword(fd, &r->pname))) { XWARNX("failed to read script name"); goto out; } else if (KCGI_OK != (ke = fullreadword(fd, &r->host))) { XWARNX("failed to read host name"); goto out; } else if (fullread(fd, &r->port, sizeof(uint16_t), 0, &ke) < 0) { XWARNX("failed to read port"); goto out; } else if (fullread(fd, &dgsz, sizeof(size_t), 0, &ke) < 0) { XWARNX("failed to read digest length"); goto out; } else if (MD5_DIGEST_LENGTH == dgsz) { /* This is a binary value. */ if (NULL == (r->rawauth.digest = XMALLOC(dgsz))) goto out; if (fullread(fd, r->rawauth.digest, dgsz, 0, &ke) < 0) { XWARNX("failed to read digest"); goto out; } } while ((rc = input(&type, &kp, fd, &ke, eofok)) > 0) { assert(type < IN__MAX); /* * We have a parsed field from the child process. * Begin by expanding the number of parsed fields * depending on whether we have a cookie or form input. * Then copy the new data. */ kpp = IN_COOKIE == type ? kpair_expand(&r->cookies, &r->cookiesz) : kpair_expand(&r->fields, &r->fieldsz); if (NULL == kpp) { rc = -1; ke = KCGI_ENOMEM; break; } *kpp = kp; } if (rc < 0) goto out; /* * Now that the field and cookie arrays are fixed and not going * to be reallocated any more, we run through both arrays and * assign the named fields into buckets. */ for (i = 0; i < r->fieldsz; i++) { kpp = &r->fields[i]; if (kpp->keypos == r->keysz) continue; if (KPAIR_INVALID != kpp->state) { kpp->next = r->fieldmap[kpp->keypos]; r->fieldmap[kpp->keypos] = kpp; } else { kpp->next = r->fieldnmap[kpp->keypos]; r->fieldnmap[kpp->keypos] = kpp; } } for (i = 0; i < r->cookiesz; i++) { kpp = &r->cookies[i]; if (kpp->keypos == r->keysz) continue; if (KPAIR_INVALID != kpp->state) { kpp->next = r->cookiemap[kpp->keypos]; r->cookiemap[kpp->keypos] = kpp; } else { kpp->next = r->cookienmap[kpp->keypos]; r->cookienmap[kpp->keypos] = kpp; } } ke = KCGI_OK; /* * Usually, "kp" would be zeroed after its memory is copied into * one of the form-input arrays. * However, in the case of error, these may still have * allocations, so free them now. */ out: free(kp.key); free(kp.val); free(kp.file); free(kp.ctype); free(kp.xcode); return(ke); }
/* read in new CRL entries and save new list */ static int SwapLists(WOLFSSL_CRL* crl) { int ret; CRL_Entry* newList; #ifdef WOLFSSL_SMALL_STACK WOLFSSL_CRL* tmp; #else WOLFSSL_CRL tmp[1]; #endif #ifdef WOLFSSL_SMALL_STACK tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) return MEMORY_E; #endif if (InitCRL(tmp, crl->cm) < 0) { WOLFSSL_MSG("Init tmp CRL failed"); #ifdef WOLFSSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return -1; } if (crl->monitors[0].path) { ret = LoadCRL(tmp, crl->monitors[0].path, SSL_FILETYPE_PEM, 0); if (ret != SSL_SUCCESS) { WOLFSSL_MSG("PEM LoadCRL on dir change failed"); FreeCRL(tmp, 0); #ifdef WOLFSSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return -1; } } if (crl->monitors[1].path) { ret = LoadCRL(tmp, crl->monitors[1].path, SSL_FILETYPE_ASN1, 0); if (ret != SSL_SUCCESS) { WOLFSSL_MSG("DER LoadCRL on dir change failed"); FreeCRL(tmp, 0); #ifdef WOLFSSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return -1; } } if (wc_LockMutex(&crl->crlLock) != 0) { WOLFSSL_MSG("wc_LockMutex failed"); FreeCRL(tmp, 0); #ifdef WOLFSSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return -1; } newList = tmp->crlList; /* swap lists */ tmp->crlList = crl->crlList; crl->crlList = newList; wc_UnLockMutex(&crl->crlLock); FreeCRL(tmp, 0); #ifdef WOLFSSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return 0; }
/* return: >0 OCSP Response Size * -1 error */ static int process_http_response(int sfd, byte** respBuf, byte* httpBuf, int httpBufSz) { int result; int len = 0; char *start, *end; byte *recvBuf = NULL; int recvBufSz = 0; enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type, phr_wait_end, phr_http_end } state = phr_init; start = end = NULL; do { if (end == NULL) { result = (int)RECV_FUNCTION(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); if (result > 0) { len += result; start = (char*)httpBuf; start[len] = 0; } else { WOLFSSL_MSG("process_http_response recv http from peer failed"); return -1; } } end = XSTRSTR(start, "\r\n"); if (end == NULL) { if (len != 0) XMEMMOVE(httpBuf, start, len); start = end = NULL; } else if (end == start) { if (state == phr_wait_end) { state = phr_http_end; len -= 2; start += 2; } else { WOLFSSL_MSG("process_http_response header ended early"); return -1; } } else { *end = 0; len -= (int)(end - start) + 2; /* adjust len to remove the first line including the /r/n */ if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { start += 9; if (XSTRNCASECMP(start, "200 OK", 6) != 0 || state != phr_init) { WOLFSSL_MSG("process_http_response not OK"); return -1; } state = phr_http_start; } else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { start += 13; while (*start == ' ' && *start != '\0') start++; if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) { WOLFSSL_MSG("process_http_response not ocsp-response"); return -1; } if (state == phr_http_start) state = phr_have_type; else if (state == phr_have_length) state = phr_wait_end; else { WOLFSSL_MSG("process_http_response type invalid state"); return -1; } } else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { start += 15; while (*start == ' ' && *start != '\0') start++; recvBufSz = atoi(start); if (state == phr_http_start) state = phr_have_length; else if (state == phr_have_type) state = phr_wait_end; else { WOLFSSL_MSG("process_http_response length invalid state"); return -1; } } start = end + 2; } } while (state != phr_http_end); recvBuf = (byte*)XMALLOC(recvBufSz, NULL, DYNAMIC_TYPE_OCSP); if (recvBuf == NULL) { WOLFSSL_MSG("process_http_response couldn't create response buffer"); return -1; } /* copy the remainder of the httpBuf into the respBuf */ if (len != 0) XMEMCPY(recvBuf, start, len); /* receive the OCSP response data */ do { result = (int)RECV_FUNCTION(sfd, (char*)recvBuf+len, recvBufSz-len, 0); if (result > 0) len += result; else { WOLFSSL_MSG("process_http_response recv ocsp from peer failed"); return -1; } } while (len != recvBufSz); *respBuf = recvBuf; return recvBufSz; }
/* linux monitoring */ static void* DoMonitor(void* arg) { int notifyFd; int wd = -1; WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg; #ifdef WOLFSSL_SMALL_STACK char* buff; #else char buff[8192]; #endif WOLFSSL_ENTER("DoMonitor"); crl->mfd = eventfd(0, 0); /* our custom shutdown event */ if (crl->mfd < 0) { WOLFSSL_MSG("eventfd failed"); SignalSetup(crl, MONITOR_SETUP_E); return NULL; } notifyFd = inotify_init(); if (notifyFd < 0) { WOLFSSL_MSG("inotify failed"); close(crl->mfd); SignalSetup(crl, MONITOR_SETUP_E); return NULL; } if (crl->monitors[0].path) { wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE | IN_DELETE); if (wd < 0) { WOLFSSL_MSG("PEM notify add watch failed"); close(crl->mfd); close(notifyFd); SignalSetup(crl, MONITOR_SETUP_E); return NULL; } } if (crl->monitors[1].path) { wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE | IN_DELETE); if (wd < 0) { WOLFSSL_MSG("DER notify add watch failed"); close(crl->mfd); close(notifyFd); SignalSetup(crl, MONITOR_SETUP_E); return NULL; } } #ifdef WOLFSSL_SMALL_STACK buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (buff == NULL) return NULL; #endif /* signal to calling thread we're setup */ if (SignalSetup(crl, 1) != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif if (wd > 0) inotify_rm_watch(notifyFd, wd); close(crl->mfd); close(notifyFd); return NULL; } for (;;) { fd_set readfds; int result; int length; FD_ZERO(&readfds); FD_SET(notifyFd, &readfds); FD_SET(crl->mfd, &readfds); result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL); WOLFSSL_MSG("Got notify event"); if (result < 0) { WOLFSSL_MSG("select problem, continue"); continue; } if (FD_ISSET(crl->mfd, &readfds)) { WOLFSSL_MSG("got custom shutdown event, breaking out"); break; } length = (int) read(notifyFd, buff, 8192); if (length < 0) { WOLFSSL_MSG("notify read problem, continue"); continue; } if (SwapLists(crl) < 0) { WOLFSSL_MSG("SwapLists problem, continue"); } } #ifdef WOLFSSL_SMALL_STACK XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif if (wd > 0) inotify_rm_watch(notifyFd, wd); close(crl->mfd); close(notifyFd); return NULL; }
Symbol* Converter::primitive_convert(STATE, Object* source, String* target, Fixnum* offset, Fixnum* size, Fixnum* options) { String* src = 0; if(!source->nil_p()) { if(!(src = try_as<String>(source))) { return force_as<Symbol>(Primitives::failure()); } } Converter* self = this; OnStack<4> os(state, self, source, src, target); const unsigned char* source_ptr = 0; const unsigned char* source_end = 0; native_int byte_offset = offset->to_native(); native_int byte_size = size->to_native(); retry: if(!self->converter_) { size_t num_converters = self->converters()->size(); self->set_converter(rb_econv_alloc(num_converters)); for(size_t i = 0; i < num_converters; i++) { Transcoding* transcoding = as<Transcoding>(self->converters()->get(state, i)); rb_transcoder* tr = transcoding->get_transcoder(); if(rb_econv_add_transcoder_at(self->converter_, tr, i) == -1) { rb_econv_free(self->get_converter()); self->set_converter(NULL); return force_as<Symbol>(Primitives::failure()); } } } /* It would be nice to have a heuristic that avoids having to reconvert * after growing the destination buffer. This is complicated, however, as * a converter may contain more than one transcoder. So, the heuristic * would need to be transitive. This requires getting the encoding objects * for every stage of the converter to check the min/max byte values. */ if(byte_size == -1) { byte_size = src ? src->byte_size() : 4096; } int flags = self->converter_->flags = options->to_native(); if(!self->replacement()->nil_p() && !self->converter_->replacement_str) { // First check the array's whether they exist so we don't // leak memory or create badly initialized C structures size_t num_converters = self->replacement_converters()->size(); for(size_t i = 0, k = 0; i < num_converters; k++, i += 2) { as<String>(self->replacement_converters()->get(state, i)); as<Array>(self->replacement_converters()->get(state, i + 1)); } native_int byte_size = self->replacement()->byte_size(); char* buf = (char*)XMALLOC(byte_size + 1); strncpy(buf, self->replacement()->c_str(state), byte_size + 1); self->converter_->replacement_str = (const unsigned char*)buf; self->converter_->replacement_len = self->replacement()->byte_size(); String* name = self->replacement()->encoding()->name(); byte_size = name->byte_size(); buf = (char*)XMALLOC(byte_size + 1); strncpy(buf, name->c_str(state), byte_size + 1); self->converter_->replacement_enc = (const char*)buf; self->converter_->replacement_allocated = 1; rb_econv_alloc_replacement_converters(self->converter_, num_converters / 2); for(size_t i = 0, k = 0; i < num_converters; k++, i += 2) { rb_econv_replacement_converters* repl_converter; repl_converter = self->converter_->replacement_converters + k; // We can use force_as here since we know type has been checked above name = force_as<String>(self->replacement_converters()->get(state, i)); byte_size = name->byte_size(); buf = (char*)XMALLOC(byte_size + 1); strncpy(buf, name->c_str(state), byte_size + 1); repl_converter->destination_encoding_name = (const char*)buf; Array* trs = force_as<Array>(replacement_converters()->get(state, i + 1)); size_t num_transcoders = trs->size(); repl_converter->num_transcoders = num_transcoders; repl_converter->transcoders = ALLOC_N(rb_transcoder*, num_transcoders); for(size_t j = 0; j < num_transcoders; j++) { Transcoding* transcoding = as<Transcoding>(trs->get(state, j)); rb_transcoder* tr = transcoding->get_transcoder(); repl_converter->transcoders[j] = tr; } } }
/* Load CRL path files of type, SSL_SUCCESS on ok */ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) { struct dirent* entry; DIR* dir; int ret = SSL_SUCCESS; #ifdef WOLFSSL_SMALL_STACK char* name; #else char name[MAX_FILENAME_SZ]; #endif WOLFSSL_ENTER("LoadCRL"); if (crl == NULL) return BAD_FUNC_ARG; dir = opendir(path); if (dir == NULL) { WOLFSSL_MSG("opendir path crl load failed"); return BAD_PATH_ERROR; } #ifdef WOLFSSL_SMALL_STACK name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (name == NULL) return MEMORY_E; #endif while ( (entry = readdir(dir)) != NULL) { struct stat s; XMEMSET(name, 0, MAX_FILENAME_SZ); XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); XSTRNCAT(name, "/", 1); XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); if (stat(name, &s) != 0) { WOLFSSL_MSG("stat on name failed"); continue; } if (s.st_mode & S_IFREG) { if (type == SSL_FILETYPE_PEM) { if (XSTRSTR(entry->d_name, ".pem") == NULL) { WOLFSSL_MSG("not .pem file, skipping"); continue; } } else { if (XSTRSTR(entry->d_name, ".der") == NULL && XSTRSTR(entry->d_name, ".crl") == NULL) { WOLFSSL_MSG("not .der or .crl file, skipping"); continue; } } if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) != SSL_SUCCESS) { WOLFSSL_MSG("CRL file load failed, continuing"); } } } #ifdef WOLFSSL_SMALL_STACK XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif if (monitor & WOLFSSL_CRL_MONITOR) { word32 pathLen; char* pathBuf; WOLFSSL_MSG("monitor path requested"); pathLen = (word32)XSTRLEN(path); pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR); if (pathBuf) { XSTRNCPY(pathBuf, path, pathLen); pathBuf[pathLen] = '\0'; /* Null Terminate */ if (type == SSL_FILETYPE_PEM) { crl->monitors[0].path = pathBuf; crl->monitors[0].type = SSL_FILETYPE_PEM; } else { crl->monitors[1].path = pathBuf; crl->monitors[1].type = SSL_FILETYPE_ASN1; } if (monitor & WOLFSSL_CRL_START_MON) { WOLFSSL_MSG("start monitoring requested"); ret = StartMonitorCRL(crl); } } else { ret = MEMORY_E; } } closedir(dir); return ret; }
/* Flush enough data to fill a terminal window of the given scene (used only by vty telnet interface). */ buffer_status_t buffer_flush_window (struct buffer *b, int fd, int width, int height, int erase_flag, int no_more_flag) { int nbytes; int iov_alloc; int iov_index; struct iovec *iov; struct iovec small_iov[3]; char more[] = " --More-- "; char erase[] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; struct buffer_data *data; int column; if (!b->head) return BUFFER_EMPTY; if (height < 1) { zlog_warn("%s called with non-positive window height %d, forcing to 1", __func__, height); height = 1; } else if (height >= 2) height--; if (width < 1) { zlog_warn("%s called with non-positive window width %d, forcing to 1", __func__, width); width = 1; } /* For erase and more data add two to b's buffer_data count.*/ if (b->head->next == NULL) { iov_alloc = sizeof(small_iov)/sizeof(small_iov[0]); iov = small_iov; } else { iov_alloc = ((height*(width+2))/b->size)+10; iov = XMALLOC(MTYPE_TMP, iov_alloc*sizeof(*iov)); } iov_index = 0; /* Previously print out is performed. */ if (erase_flag) { iov[iov_index].iov_base = erase; iov[iov_index].iov_len = sizeof erase; iov_index++; } /* Output data. */ column = 1; /* Column position of next character displayed. */ for (data = b->head; data && (height > 0); data = data->next) { size_t cp; cp = data->sp; while ((cp < data->cp) && (height > 0)) { /* Calculate lines remaining and column position after displaying this character. */ if (data->data[cp] == '\r') column = 1; else if ((data->data[cp] == '\n') || (column == width)) { column = 1; height--; } else column++; cp++; } iov[iov_index].iov_base = (char *)(data->data + data->sp); iov[iov_index++].iov_len = cp-data->sp; data->sp = cp; if (iov_index == iov_alloc) /* This should not ordinarily happen. */ { iov_alloc *= 2; if (iov != small_iov) { zlog_warn("%s: growing iov array to %d; " "width %d, height %d, size %lu", __func__, iov_alloc, width, height, (u_long)b->size); iov = XREALLOC(MTYPE_TMP, iov, iov_alloc*sizeof(*iov)); } else { /* This should absolutely never occur. */ zlog_err("%s: corruption detected: iov_small overflowed; " "head %p, tail %p, head->next %p", __func__, b->head, b->tail, b->head->next); iov = XMALLOC(MTYPE_TMP, iov_alloc*sizeof(*iov)); memcpy(iov, small_iov, sizeof(small_iov)); } } } /* In case of `more' display need. */ if (b->tail && (b->tail->sp < b->tail->cp) && !no_more_flag) { iov[iov_index].iov_base = more; iov[iov_index].iov_len = sizeof more; iov_index++; } #ifdef IOV_MAX /* IOV_MAX are normally defined in <sys/uio.h> , Posix.1g. example: Solaris2.6 are defined IOV_MAX size at 16. */ { struct iovec *c_iov = iov; nbytes = 0; /* Make sure it's initialized. */ while (iov_index > 0) { int iov_size; /*CID 12128 (#1 of 1): Out-of-bounds access (OVERRUN) 35. overrun-buffer-arg: Overrunning buffer pointed to by "c_iov" of 3 8-byte elements by passing it to a function which accesses it at element index 1023 (byte offset 8184) using argument "iov_size" (which evaluates to 1024).*/ /*But this func buffer_flush_window, now we donnot use .*/ iov_size = ((iov_index > IOV_MAX) ? IOV_MAX : iov_index); if ((nbytes = writev(fd, c_iov, iov_size)) < 0) { zlog_warn("%s: writev to fd %d failed: %s", __func__, fd, safe_strerror(errno)); break; } /* move pointer io-vector */ c_iov += iov_size; iov_index -= iov_size; } } #else /* IOV_MAX */ if ((nbytes = writev (fd, iov, iov_index)) < 0) zlog_warn("%s: writev to fd %d failed: %s", __func__, fd, safe_strerror(errno)); #endif /* IOV_MAX */ /* Free printed buffer data. */ while (b->head && (b->head->sp == b->head->cp)) { struct buffer_data *del; if (!(b->head = (del = b->head)->next)) b->tail = NULL; BUFFER_DATA_FREE(del); } if (iov != small_iov) XFREE (MTYPE_TMP, iov); return (nbytes < 0) ? BUFFER_ERROR : (b->head ? BUFFER_PENDING : BUFFER_EMPTY); }
/** ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements. @param in The input buffer @param inlen [in/out] The length of the input buffer and on output the amount of decoded data @param out [out] A pointer to the linked list @return CRYPT_OK on success. */ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out) { ltc_asn1_list *l; unsigned long err, type, len, totlen, data_offset; void *realloc_tmp; LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != NULL); LTC_ARGCHK(out != NULL); l = NULL; totlen = 0; if (*inlen == 0) { /* alloc new link */ if ((err = _new_element(&l)) != CRYPT_OK) { goto error; } } /* scan the input and and get lengths and what not */ while (*inlen) { /* read the type byte */ type = *in; /* fetch length */ len = _fetch_length(in, *inlen, &data_offset); if (len > *inlen) { err = CRYPT_INVALID_PACKET; goto error; } /* alloc new link */ if ((err = _new_element(&l)) != CRYPT_OK) { goto error; } if ((type & 0x20) && (type != 0x30) && (type != 0x31)) { /* constructed, use the 'used' field to store the original identifier */ l->used = type; /* treat constructed elements like SETs */ type = 0x20; } else if ((type & 0xC0) == 0x80) { /* context-specific, use the 'used' field to store the original identifier */ l->used = type; /* context-specific elements are treated as opaque data */ type = 0x80; } /* now switch on type */ switch (type) { case 0x01: /* BOOLEAN */ l->type = LTC_ASN1_BOOLEAN; l->size = 1; l->data = XCALLOC(1, sizeof(int)); if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) { goto error; } if ((err = der_length_boolean(&len)) != CRYPT_OK) { goto error; } break; case 0x02: /* INTEGER */ /* init field */ l->type = LTC_ASN1_INTEGER; l->size = 1; if ((err = mp_init(&l->data)) != CRYPT_OK) { goto error; } /* decode field */ if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) { goto error; } /* calc length of object */ if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) { goto error; } break; case 0x03: /* BIT */ /* init field */ l->type = LTC_ASN1_BIT_STRING; l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */ if ((l->data = XCALLOC(1, l->size)) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x04: /* OCTET */ /* init field */ l->type = LTC_ASN1_OCTET_STRING; l->size = len; if ((l->data = XCALLOC(1, l->size)) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x05: /* NULL */ /* valid NULL is 0x05 0x00 */ if (in[0] != 0x05 || in[1] != 0x00) { err = CRYPT_INVALID_PACKET; goto error; } /* simple to store ;-) */ l->type = LTC_ASN1_NULL; l->data = NULL; l->size = 0; len = 2; break; case 0x06: /* OID */ /* init field */ l->type = LTC_ASN1_OBJECT_IDENTIFIER; l->size = len; if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) { goto error; } /* resize it to save a bunch of mem */ if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) { /* out of heap but this is not an error */ break; } l->data = realloc_tmp; break; case 0x0C: /* UTF8 */ /* init field */ l->type = LTC_ASN1_UTF8_STRING; l->size = len; if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x13: /* PRINTABLE */ /* init field */ l->type = LTC_ASN1_PRINTABLE_STRING; l->size = len; if ((l->data = XCALLOC(1, l->size)) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x14: /* TELETEXT */ /* init field */ l->type = LTC_ASN1_TELETEX_STRING; l->size = len; if ((l->data = XCALLOC(1, l->size)) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_teletex_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_teletex_string(l->data, l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x16: /* IA5 */ /* init field */ l->type = LTC_ASN1_IA5_STRING; l->size = len; if ((l->data = XCALLOC(1, l->size)) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x17: /* UTC TIME */ /* init field */ l->type = LTC_ASN1_UTCTIME; l->size = 1; if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) { err = CRYPT_MEM; goto error; } len = *inlen; if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) { goto error; } if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) { goto error; } break; case 0x18: l->type = LTC_ASN1_GENERALIZEDTIME; l->size = len; if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_generalizedtime(in, &len, l->data)) != CRYPT_OK) { goto error; } if ((err = der_length_generalizedtime(l->data, &len)) != CRYPT_OK) { goto error; } break; case 0x20: /* Any CONSTRUCTED element that is neither SEQUENCE nor SET */ case 0x30: /* SEQUENCE */ case 0x31: /* SET */ /* init field */ if (type == 0x20) { l->type = LTC_ASN1_CONSTRUCTED; } else if (type == 0x30) { l->type = LTC_ASN1_SEQUENCE; } else { l->type = LTC_ASN1_SET; } if ((l->data = XMALLOC(len)) == NULL) { err = CRYPT_MEM; goto error; } XMEMCPY(l->data, in, len); l->size = len; /* jump to the start of the data */ in += data_offset; *inlen -= data_offset; len = len - data_offset; /* Sequence elements go as child */ if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) { goto error; } /* len update */ totlen += data_offset; /* the flexi decoder can also do nothing, so make sure a child has been allocated */ if (l->child) { /* link them up y0 */ l->child->parent = l; } break; case 0x80: /* Context-specific */ l->type = LTC_ASN1_CONTEXT_SPECIFIC; if ((l->data = XCALLOC(1, len - data_offset)) == NULL) { err = CRYPT_MEM; goto error; } XMEMCPY(l->data, in + data_offset, len - data_offset); l->size = len - data_offset; break; default: /* invalid byte ... this is a soft error */ /* remove link */ if (l->prev) { l = l->prev; XFREE(l->next); l->next = NULL; } goto outside; } /* advance pointers */ totlen += len; in += len; *inlen -= len; } outside: /* in case we processed anything */ if (totlen) { /* rewind l please */ while (l->prev != NULL || l->parent != NULL) { if (l->parent != NULL) { l = l->parent; } else { l = l->prev; } } } /* return */ *out = l; *inlen = totlen; return CRYPT_OK; error: /* free list */ der_sequence_free(l); return err; }