static int rand_bytes(unsigned char *buf, int num, int pseudo) { static volatile int stirred_pool = 0; int i, j, k; size_t num_ceil, st_idx, st_num; int ok; long md_c[2]; unsigned char local_md[MD_DIGEST_LENGTH]; EVP_MD_CTX *m; #ifndef GETPID_IS_MEANINGLESS pid_t curr_pid = getpid(); #endif time_t curr_time = time(NULL); int do_stir_pool = 0; /* time value for various platforms */ #ifdef OPENSSL_SYS_WIN32 FILETIME tv; # ifdef _WIN32_WCE SYSTEMTIME t; GetSystemTime(&t); SystemTimeToFileTime(&t, &tv); # else GetSystemTimeAsFileTime(&tv); # endif #elif defined(OPENSSL_SYS_VXWORKS) struct timespec tv; clock_gettime(CLOCK_REALTIME, &ts); #elif defined(OPENSSL_SYS_DSPBIOS) unsigned long long tv, OPENSSL_rdtsc(); tv = OPENSSL_rdtsc(); #else struct timeval tv; gettimeofday(&tv, NULL); #endif #ifdef PREDICT if (rand_predictable) { static unsigned char val = 0; for (i = 0; i < num; i++) buf[i] = val++; return (1); } #endif if (num <= 0) return 1; m = EVP_MD_CTX_new(); if (m == NULL) goto err_mem; /* round upwards to multiple of MD_DIGEST_LENGTH/2 */ num_ceil = (1 + (num - 1) / (MD_DIGEST_LENGTH / 2)) * (MD_DIGEST_LENGTH / 2); /* * (Based on the rand(3) manpage:) * * For each group of 10 bytes (or less), we do the following: * * Input into the hash function the local 'md' (which is initialized from * the global 'md' before any bytes are generated), the bytes that are to * be overwritten by the random bytes, and bytes from the 'state' * (incrementing looping index). From this digest output (which is kept * in 'md'), the top (up to) 10 bytes are returned to the caller and the * bottom 10 bytes are xored into the 'state'. * * Finally, after we have finished 'num' random bytes for the * caller, 'count' (which is incremented) and the local and global 'md' * are fed into the hash function and the results are kept in the * global 'md'. */ if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) goto err_mem; CRYPTO_THREAD_write_lock(rand_lock); /* * We could end up in an async engine while holding this lock so ensure * we don't pause and cause a deadlock */ ASYNC_block_pause(); /* prevent rand_bytes() from trying to obtain the lock again */ CRYPTO_THREAD_write_lock(rand_tmp_lock); locking_threadid = CRYPTO_THREAD_get_current_id(); CRYPTO_THREAD_unlock(rand_tmp_lock); crypto_lock_rand = 1; if (!initialized) { RAND_poll(); initialized = 1; } if (!stirred_pool) do_stir_pool = 1; ok = (entropy >= ENTROPY_NEEDED); if (!ok) { /* * If the PRNG state is not yet unpredictable, then seeing the PRNG * output may help attackers to determine the new state; thus we have * to decrease the entropy estimate. Once we've had enough initial * seeding we don't bother to adjust the entropy count, though, * because we're not ambitious to provide *information-theoretic* * randomness. NOTE: This approach fails if the program forks before * we have enough entropy. Entropy should be collected in a separate * input pool and be transferred to the output pool only when the * entropy limit has been reached. */ entropy -= num; if (entropy < 0) entropy = 0; } if (do_stir_pool) { /* * In the output function only half of 'md' remains secret, so we * better make sure that the required entropy gets 'evenly * distributed' through 'state', our randomness pool. The input * function (rand_add) chains all of 'md', which makes it more * suitable for this purpose. */ int n = STATE_SIZE; /* so that the complete pool gets accessed */ while (n > 0) { #if MD_DIGEST_LENGTH > 20 # error "Please adjust DUMMY_SEED." #endif #define DUMMY_SEED "...................." /* at least MD_DIGEST_LENGTH */ /* * Note that the seed does not matter, it's just that * rand_add expects to have something to hash. */ rand_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0); n -= MD_DIGEST_LENGTH; } if (ok) stirred_pool = 1; } st_idx = state_index; st_num = state_num; md_c[0] = md_count[0]; md_c[1] = md_count[1]; memcpy(local_md, md, sizeof md); state_index += num_ceil; if (state_index > state_num) state_index %= state_num; /* * state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num] are now * ours (but other threads may use them too) */ md_count[0] += 1; /* before unlocking, we must clear 'crypto_lock_rand' */ crypto_lock_rand = 0; ASYNC_unblock_pause(); CRYPTO_THREAD_unlock(rand_lock); while (num > 0) { /* num_ceil -= MD_DIGEST_LENGTH/2 */ j = (num >= MD_DIGEST_LENGTH / 2) ? MD_DIGEST_LENGTH / 2 : num; num -= j; if (!MD_Init(m)) goto err; #ifndef GETPID_IS_MEANINGLESS if (curr_pid) { /* just in the first iteration to save time */ if (!MD_Update(m, (unsigned char *)&curr_pid, sizeof curr_pid)) goto err; curr_pid = 0; } #endif if (curr_time) { /* just in the first iteration to save time */ if (!MD_Update(m, (unsigned char *)&curr_time, sizeof curr_time)) goto err; if (!MD_Update(m, (unsigned char *)&tv, sizeof tv)) goto err; curr_time = 0; if (!rand_hw_seed(m)) goto err; } if (!MD_Update(m, local_md, MD_DIGEST_LENGTH)) goto err; if (!MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c))) goto err; k = (st_idx + MD_DIGEST_LENGTH / 2) - st_num; if (k > 0) { if (!MD_Update(m, &(state[st_idx]), MD_DIGEST_LENGTH / 2 - k)) goto err; if (!MD_Update(m, &(state[0]), k)) goto err; } else if (!MD_Update(m, &(state[st_idx]), MD_DIGEST_LENGTH / 2)) goto err; if (!MD_Final(m, local_md)) goto err; for (i = 0; i < MD_DIGEST_LENGTH / 2; i++) { /* may compete with other threads */ state[st_idx++] ^= local_md[i]; if (st_idx >= st_num) st_idx = 0; if (i < j) *(buf++) = local_md[i + MD_DIGEST_LENGTH / 2]; } } if (!MD_Init(m) || !MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c)) || !MD_Update(m, local_md, MD_DIGEST_LENGTH)) goto err; CRYPTO_THREAD_write_lock(rand_lock); /* * Prevent deadlocks if we end up in an async engine */ ASYNC_block_pause(); if (!MD_Update(m, md, MD_DIGEST_LENGTH) || !MD_Final(m, md)) { CRYPTO_THREAD_unlock(rand_lock); goto err; } ASYNC_unblock_pause(); CRYPTO_THREAD_unlock(rand_lock); EVP_MD_CTX_free(m); if (ok) return (1); else if (pseudo) return 0; else { RANDerr(RAND_F_RAND_BYTES, RAND_R_PRNG_NOT_SEEDED); ERR_add_error_data(1, "You need to read the OpenSSL FAQ, " "https://www.openssl.org/docs/faq.html"); return (0); } err: RANDerr(RAND_F_RAND_BYTES, ERR_R_EVP_LIB); EVP_MD_CTX_free(m); return 0; err_mem: RANDerr(RAND_F_RAND_BYTES, ERR_R_MALLOC_FAILURE); EVP_MD_CTX_free(m); return 0; }
static int ssleay_rand_bytes(unsigned char *buf, int num) { static volatile int stirred_pool = 0; int i,j,k,st_num,st_idx; int num_ceil; int ok; long md_c[2]; unsigned char local_md[MD_DIGEST_LENGTH]; EVP_MD_CTX m; #ifndef GETPID_IS_MEANINGLESS pid_t curr_pid = TINYCLR_SSL_GETPID(); #endif int do_stir_pool = 0; #ifdef PREDICT if (rand_predictable) { static unsigned char val=0; for (i=0; i<num; i++) buf[i]=val++; return(1); } #endif if (num <= 0) return 1; EVP_MD_CTX_init(&m); /* round upwards to multiple of MD_DIGEST_LENGTH/2 */ num_ceil = (1 + (num-1)/(MD_DIGEST_LENGTH/2)) * (MD_DIGEST_LENGTH/2); /* * (Based on the rand(3) manpage:) * * For each group of 10 bytes (or less), we do the following: * * Input into the hash function the local 'md' (which is initialized from * the global 'md' before any bytes are generated), the bytes that are to * be overwritten by the random bytes, and bytes from the 'state' * (incrementing looping index). From this digest output (which is kept * in 'md'), the top (up to) 10 bytes are returned to the caller and the * bottom 10 bytes are xored into the 'state'. * * Finally, after we have finished 'num' random bytes for the * caller, 'count' (which is incremented) and the local and global 'md' * are fed into the hash function and the results are kept in the * global 'md'. */ CRYPTO_w_lock(CRYPTO_LOCK_RAND); /* prevent ssleay_rand_bytes() from trying to obtain the lock again */ CRYPTO_w_lock(CRYPTO_LOCK_RAND2); CRYPTO_THREADID_current(&locking_threadid); CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); crypto_lock_rand = 1; if (!initialized) { RAND_poll(); initialized = 1; } if (!stirred_pool) do_stir_pool = 1; ok = (entropy >= ENTROPY_NEEDED); if (!ok) { /* If the PRNG state is not yet unpredictable, then seeing * the PRNG output may help attackers to determine the new * state; thus we have to decrease the entropy estimate. * Once we've had enough initial seeding we don't bother to * adjust the entropy count, though, because we're not ambitious * to provide *information-theoretic* randomness. * * NOTE: This approach fails if the program forks before * we have enough entropy. Entropy should be collected * in a separate input pool and be transferred to the * output pool only when the entropy limit has been reached. */ entropy -= num; if (entropy < 0) entropy = 0; } if (do_stir_pool) { /* In the output function only half of 'md' remains secret, * so we better make sure that the required entropy gets * 'evenly distributed' through 'state', our randomness pool. * The input function (ssleay_rand_add) chains all of 'md', * which makes it more suitable for this purpose. */ int n = STATE_SIZE; /* so that the complete pool gets accessed */ while (n > 0) { #if MD_DIGEST_LENGTH > 20 # error "Please adjust DUMMY_SEED." #endif #define DUMMY_SEED "...................." /* at least MD_DIGEST_LENGTH */ /* Note that the seed does not matter, it's just that * ssleay_rand_add expects to have something to hash. */ ssleay_rand_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0); n -= MD_DIGEST_LENGTH; } if (ok) stirred_pool = 1; } st_idx=state_index; st_num=state_num; md_c[0] = md_count[0]; md_c[1] = md_count[1]; TINYCLR_SSL_MEMCPY(local_md, md, sizeof md); state_index+=num_ceil; if (state_index > state_num) state_index %= state_num; /* state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num] * are now ours (but other threads may use them too) */ md_count[0] += 1; /* before unlocking, we must clear 'crypto_lock_rand' */ crypto_lock_rand = 0; CRYPTO_w_unlock(CRYPTO_LOCK_RAND); while (num > 0) { /* num_ceil -= MD_DIGEST_LENGTH/2 */ j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num; num-=j; MD_Init(&m); #ifndef GETPID_IS_MEANINGLESS if (curr_pid) /* just in the first iteration to save time */ { MD_Update(&m,(unsigned char*)&curr_pid,sizeof curr_pid); curr_pid = 0; } #endif MD_Update(&m,local_md,MD_DIGEST_LENGTH); MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); #ifndef PURIFY /* purify complains */ /* The following line uses the supplied buffer as a small * source of entropy: since this buffer is often uninitialised * it may cause programs such as purify or valgrind to * complain. So for those builds it is not used: the removal * of such a small source of entropy has negligible impact on * security. */ MD_Update(&m,buf,j); #endif k=(st_idx+MD_DIGEST_LENGTH/2)-st_num; if (k > 0) { MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2-k); MD_Update(&m,&(state[0]),k); } else MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2); MD_Final(&m,local_md); for (i=0; i<MD_DIGEST_LENGTH/2; i++) { state[st_idx++]^=local_md[i]; /* may compete with other threads */ if (st_idx >= st_num) st_idx=0; if (i < j) *(buf++)=local_md[i+MD_DIGEST_LENGTH/2]; } } MD_Init(&m); MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c)); MD_Update(&m,local_md,MD_DIGEST_LENGTH); CRYPTO_w_lock(CRYPTO_LOCK_RAND); MD_Update(&m,md,MD_DIGEST_LENGTH); MD_Final(&m,md); CRYPTO_w_unlock(CRYPTO_LOCK_RAND); EVP_MD_CTX_cleanup(&m); if (ok) return(1); else { RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED); ERR_add_error_data(1, "You need to read the OpenSSL FAQ, " "http://www.openssl.org/support/faq.html"); return(0); } }
static char *vms_merger(DSO *dso, const char *filespec1, const char *filespec2) { int status; int filespec1len, filespec2len; struct FAB fab; struct NAMX_STRUCT nam; char esa[NAMX_MAXRSS + 1]; char *merged; /* Arrange 32-bit pointer to (copied) string storage, if needed. */ # if __INITIAL_POINTER_SIZE == 64 # define FILESPEC1 filespec1_32p; # define FILESPEC2 filespec2_32p; # pragma pointer_size save # pragma pointer_size 32 char *filespec1_32p; char *filespec2_32p; # pragma pointer_size restore char filespec1_32[NAMX_MAXRSS + 1]; char filespec2_32[NAMX_MAXRSS + 1]; # else /* __INITIAL_POINTER_SIZE == 64 */ # define FILESPEC1 ((char *) filespec1) # define FILESPEC2 ((char *) filespec2) # endif /* __INITIAL_POINTER_SIZE == 64 [else] */ if (!filespec1) filespec1 = ""; if (!filespec2) filespec2 = ""; filespec1len = strlen(filespec1); filespec2len = strlen(filespec2); # if __INITIAL_POINTER_SIZE == 64 /* Copy the file names to storage with a 32-bit pointer. */ filespec1_32p = filespec1_32; filespec2_32p = filespec2_32; strcpy(filespec1_32p, filespec1); strcpy(filespec2_32p, filespec2); # endif /* __INITIAL_POINTER_SIZE == 64 [else] */ fab = cc$rms_fab; nam = CC_RMS_NAMX; FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNA = FILESPEC1; FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNS = filespec1len; FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNA = FILESPEC2; FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNS = filespec2len; NAMX_DNA_FNA_SET(fab) nam.NAMX_ESA = esa; nam.NAMX_ESS = NAMX_MAXRSS; nam.NAMX_NOP = NAM$M_SYNCHK | NAM$M_PWD; SET_NAMX_NO_SHORT_UPCASE(nam); fab.FAB_NAMX = &nam; status = sys$parse(&fab, 0, 0); if (!$VMS_STATUS_SUCCESS(status)) { unsigned short length; char errstring[257]; struct dsc$descriptor_s errstring_dsc; errstring_dsc.dsc$w_length = sizeof(errstring); errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T; errstring_dsc.dsc$b_class = DSC$K_CLASS_S; errstring_dsc.dsc$a_pointer = errstring; status = sys$getmsg(status, &length, &errstring_dsc, 1, 0); if (!$VMS_STATUS_SUCCESS(status)) lib$signal(status); /* This is really bad. Abort! */ else { errstring[length] = '\0'; DSOerr(DSO_F_VMS_MERGER, DSO_R_FAILURE); ERR_add_error_data(7, "filespec \"", filespec1, "\", ", "defaults \"", filespec2, "\": ", errstring); } return (NULL); } merged = OPENSSL_malloc(nam.NAMX_ESL + 1); if (!merged) goto malloc_err; strncpy(merged, nam.NAMX_ESA, nam.NAMX_ESL); merged[nam.NAMX_ESL] = '\0'; return (merged); malloc_err: DSOerr(DSO_F_VMS_MERGER, ERR_R_MALLOC_FAILURE); }
static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret=1; FILE *fp=(FILE *)b->ptr; FILE **fpp; char p[4]; switch (cmd) { case BIO_C_FILE_SEEK: case BIO_CTRL_RESET: if (b->flags&BIO_FLAGS_UPLINK) ret=(long)UP_fseek(b->ptr,num,0); else ret=(long)fseek(fp,num,0); break; case BIO_CTRL_EOF: if (b->flags&BIO_FLAGS_UPLINK) ret=(long)UP_feof(fp); else ret=(long)feof(fp); break; case BIO_C_FILE_TELL: case BIO_CTRL_INFO: if (b->flags&BIO_FLAGS_UPLINK) ret=UP_ftell(b->ptr); else ret=ftell(fp); break; case BIO_C_SET_FILE_PTR: file_free(b); b->shutdown=(int)num&BIO_CLOSE; b->ptr=ptr; b->init=1; #if BIO_FLAGS_UPLINK!=0 #if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES) #define _IOB_ENTRIES 20 #endif #if defined(_IOB_ENTRIES) /* Safety net to catch purely internal BIO_set_fp calls */ if ((size_t)ptr >= (size_t)stdin && (size_t)ptr < (size_t)(stdin+_IOB_ENTRIES)) BIO_clear_flags(b,BIO_FLAGS_UPLINK); #endif #endif #ifdef UP_fsetmode if (b->flags&BIO_FLAGS_UPLINK) UP_fsetmode(b->ptr,num&BIO_FP_TEXT?'t':'b'); else #endif { #if defined(OPENSSL_SYS_WINCE) FILE *fd = _fileno((FILE*)ptr); if (num & BIO_FP_TEXT) _setmode(fd,_O_TEXT); else _setmode(fd,_O_BINARY); #elif defined(OPENSSL_SYS_WINDOWS) int fd = _fileno((FILE*)ptr); if (num & BIO_FP_TEXT) _setmode(fd,_O_TEXT); else _setmode(fd,_O_BINARY); #elif defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB) int fd = fileno((FILE*)ptr); /* Under CLib there are differences in file modes */ if (num & BIO_FP_TEXT) setmode(fd,O_TEXT); else setmode(fd,O_BINARY); #elif defined(OPENSSL_SYS_MSDOS) int fd = fileno((FILE*)ptr); /* Set correct text/binary mode */ if (num & BIO_FP_TEXT) _setmode(fd,_O_TEXT); /* Dangerous to set stdin/stdout to raw (unless redirected) */ else { if (fd == STDIN_FILENO || fd == STDOUT_FILENO) { if (isatty(fd) <= 0) _setmode(fd,_O_BINARY); } else _setmode(fd,_O_BINARY); } #elif defined(OPENSSL_SYS_OS2) int fd = fileno((FILE*)ptr); if (num & BIO_FP_TEXT) setmode(fd, O_TEXT); else setmode(fd, O_BINARY); #endif } break; case BIO_C_SET_FILENAME: file_free(b); b->shutdown=(int)num&BIO_CLOSE; if (num & BIO_FP_APPEND) { if (num & BIO_FP_READ) BUF_strlcpy(p,"a+",sizeof p); else BUF_strlcpy(p,"a",sizeof p); } else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) BUF_strlcpy(p,"r+",sizeof p); else if (num & BIO_FP_WRITE) BUF_strlcpy(p,"w",sizeof p); else if (num & BIO_FP_READ) BUF_strlcpy(p,"r",sizeof p); else { BIOerr(BIO_F_FILE_CTRL,BIO_R_BAD_FOPEN_MODE); ret=0; break; } #if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN) if (!(num & BIO_FP_TEXT)) strcat(p,"b"); else strcat(p,"t"); #endif #if defined(OPENSSL_SYS_NETWARE) if (!(num & BIO_FP_TEXT)) strcat(p,"b"); else strcat(p,"t"); #endif fp=fopen(ptr,p); if (fp == NULL) { SYSerr(SYS_F_FOPEN,get_last_sys_error()); ERR_add_error_data(5,"fopen('",ptr,"','",p,"')"); BIOerr(BIO_F_FILE_CTRL,ERR_R_SYS_LIB); ret=0; break; } b->ptr=fp; b->init=1; BIO_clear_flags(b,BIO_FLAGS_UPLINK); /* we did fopen -> we disengage UPLINK */ break; case BIO_C_GET_FILE_PTR: /* the ptr parameter is actually a FILE ** in this case. */ if (ptr != NULL) { fpp=(FILE **)ptr; *fpp=(FILE *)b->ptr; } break; case BIO_CTRL_GET_CLOSE: ret=(long)b->shutdown; break; case BIO_CTRL_SET_CLOSE: b->shutdown=(int)num; break; case BIO_CTRL_FLUSH: if (b->flags&BIO_FLAGS_UPLINK) UP_fflush(b->ptr); else fflush((FILE *)b->ptr); break; case BIO_CTRL_DUP: ret=1; break; case BIO_CTRL_WPENDING: case BIO_CTRL_PENDING: case BIO_CTRL_PUSH: case BIO_CTRL_POP: default: ret=0; break; } return(ret); }
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, int inform, unsigned long mask, long minsize, long maxsize) { int str_type; int ret; char free_out; int outform, outlen = 0; ASN1_STRING *dest; unsigned char *p; int nchar; char strbuf[32]; int (*cpyfunc)(unsigned long,void *) = NULL; if(len == -1) len = strlen((const char *)in); if(!mask) mask = DIRSTRING_TYPE; /* First do a string check and work out the number of characters */ switch(inform) { case MBSTRING_BMP: if(len & 1) { ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_INVALID_BMPSTRING_LENGTH); return -1; } nchar = len >> 1; break; case MBSTRING_UNIV: if(len & 3) { ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); return -1; } nchar = len >> 2; break; case MBSTRING_UTF8: nchar = 0; /* This counts the characters and does utf8 syntax checking */ ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar); if(ret < 0) { ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_INVALID_UTF8STRING); return -1; } break; case MBSTRING_ASC: nchar = len; break; default: ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_UNKNOWN_FORMAT); return -1; } if((minsize > 0) && (nchar < minsize)) { ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_SHORT); BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize); ERR_add_error_data(2, "minsize=", strbuf); return -1; } if((maxsize > 0) && (nchar > maxsize)) { ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG); BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize); ERR_add_error_data(2, "maxsize=", strbuf); return -1; } /* Now work out minimal type (if any) */ if(traverse_string(in, len, inform, type_str, &mask) < 0) { ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_ILLEGAL_CHARACTERS); return -1; } /* Now work out output format and string type */ outform = MBSTRING_ASC; if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING; else if(mask & B_ASN1_IA5STRING) str_type = V_ASN1_IA5STRING; else if(mask & B_ASN1_T61STRING) str_type = V_ASN1_T61STRING; else if(mask & B_ASN1_BMPSTRING) { str_type = V_ASN1_BMPSTRING; outform = MBSTRING_BMP; } else if(mask & B_ASN1_UNIVERSALSTRING) { str_type = V_ASN1_UNIVERSALSTRING; outform = MBSTRING_UNIV; } else { str_type = V_ASN1_UTF8STRING; outform = MBSTRING_UTF8; } if(!out) return str_type; if(*out) { free_out = 0; dest = *out; if(dest->data) { dest->length = 0; OPENSSL_free(dest->data); dest->data = NULL; } dest->type = str_type; } else { free_out = 1; dest = ASN1_STRING_type_new(str_type); if(!dest) { ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE); return -1; } *out = dest; } /* If both the same type just copy across */ if(inform == outform) { if(!ASN1_STRING_set(dest, in, len)) { ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,ERR_R_MALLOC_FAILURE); return -1; } return str_type; } /* Work out how much space the destination will need */ switch(outform) { case MBSTRING_ASC: outlen = nchar; cpyfunc = cpy_asc; break; case MBSTRING_BMP: outlen = nchar << 1; cpyfunc = cpy_bmp; break; case MBSTRING_UNIV: outlen = nchar << 2; cpyfunc = cpy_univ; break; case MBSTRING_UTF8: outlen = 0; traverse_string(in, len, inform, out_utf8, &outlen); cpyfunc = cpy_utf8; break; } if(!(p = OPENSSL_malloc(outlen + 1))) { if(free_out) ASN1_STRING_free(dest); ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,ERR_R_MALLOC_FAILURE); return -1; } dest->length = outlen; dest->data = p; p[outlen] = 0; traverse_string(in, len, inform, cpyfunc, &p); return str_type; }
int UI_set_result(UI *ui, UI_STRING *uis, const char *result) { int l = strlen(result); ui->flags &= ~UI_FLAG_REDOABLE; if (!uis) return -1; switch (uis->type) { case UIT_PROMPT: case UIT_VERIFY: { char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize) + 1]; char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize) + 1]; BIO_snprintf(number1, sizeof(number1), "%d", uis->_.string_data.result_minsize); BIO_snprintf(number2, sizeof(number2), "%d", uis->_.string_data.result_maxsize); if (l < uis->_.string_data.result_minsize) { ui->flags |= UI_FLAG_REDOABLE; UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_SMALL); ERR_add_error_data(5, "You must type in ", number1, " to ", number2, " characters"); return -1; } if (l > uis->_.string_data.result_maxsize) { ui->flags |= UI_FLAG_REDOABLE; UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_LARGE); ERR_add_error_data(5, "You must type in ", number1, " to ", number2, " characters"); return -1; } } if (!uis->result_buf) { UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); return -1; } BUF_strlcpy(uis->result_buf, result, uis->_.string_data.result_maxsize + 1); break; case UIT_BOOLEAN: { const char *p; if (!uis->result_buf) { UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); return -1; } uis->result_buf[0] = '\0'; for (p = result; *p; p++) { if (strchr(uis->_.boolean_data.ok_chars, *p)) { uis->result_buf[0] = uis->_.boolean_data.ok_chars[0]; break; } if (strchr(uis->_.boolean_data.cancel_chars, *p)) { uis->result_buf[0] = uis->_.boolean_data.cancel_chars[0]; break; } } } default: break; } return 0; }
ENGINE *ENGINE_by_id(const char *id) { ENGINE *iterator; char *load_dir = NULL; if(id == NULL) { ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_PASSED_NULL_PARAMETER); return NULL; } CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); iterator = engine_list_head; while(iterator && (strcmp(id, iterator->id) != 0)) iterator = iterator->next; if(iterator) { /* We need to return a structural reference. If this is an * ENGINE type that returns copies, make a duplicate - otherwise * increment the existing ENGINE's reference count. */ if(iterator->flags & ENGINE_FLAGS_BY_ID_COPY) { ENGINE *cp = ENGINE_new(); if(!cp) iterator = NULL; else { engine_cpy(cp, iterator); iterator = cp; } } else { iterator->struct_ref++; engine_ref_debug(iterator, 0, 1) } } CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); #if 0 if(iterator == NULL) { ENGINEerr(ENGINE_F_ENGINE_BY_ID, ENGINE_R_NO_SUCH_ENGINE); ERR_add_error_data(2, "id=", id); } return iterator; #else /* EEK! Experimental code starts */ if(iterator) return iterator; /* Prevent infinite recusrion if we're looking for the dynamic engine. */ if (strcmp(id, "dynamic")) { #ifdef OPENSSL_SYS_VMS if((load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = "SSLROOT:[ENGINES]"; #else if((load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = ENGINESDIR; #endif iterator = ENGINE_by_id("dynamic"); if(!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) || !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) || !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD", load_dir, 0) || !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0)) goto notfound; return iterator; } notfound: ENGINE_free(iterator); ENGINEerr(ENGINE_F_ENGINE_BY_ID,ENGINE_R_NO_SUCH_ENGINE); ERR_add_error_data(2, "id=", id); return NULL; /* EEK! Experimental code ends */ #endif }
static int ssl_module_init(CONF_IMODULE *md, const CONF *cnf) { size_t i, j, cnt; int rv = 0; const char *ssl_conf_section; STACK_OF(CONF_VALUE) *cmd_lists; ssl_conf_section = CONF_imodule_get_value(md); cmd_lists = NCONF_get_section(cnf, ssl_conf_section); if (sk_CONF_VALUE_num(cmd_lists) <= 0) { if (cmd_lists == NULL) SSLerr(SSL_F_SSL_MODULE_INIT, SSL_R_SSL_SECTION_NOT_FOUND); else SSLerr(SSL_F_SSL_MODULE_INIT, SSL_R_SSL_SECTION_EMPTY); ERR_add_error_data(2, "section=", ssl_conf_section); goto err; } cnt = sk_CONF_VALUE_num(cmd_lists); ssl_names = OPENSSL_zalloc(sizeof(*ssl_names) * cnt); ssl_names_count = cnt; for (i = 0; i < ssl_names_count; i++) { struct ssl_conf_name *ssl_name = ssl_names + i; CONF_VALUE *sect = sk_CONF_VALUE_value(cmd_lists, i); STACK_OF(CONF_VALUE) *cmds = NCONF_get_section(cnf, sect->value); if (sk_CONF_VALUE_num(cmds) <= 0) { if (cmds == NULL) SSLerr(SSL_F_SSL_MODULE_INIT, SSL_R_SSL_COMMAND_SECTION_NOT_FOUND); else SSLerr(SSL_F_SSL_MODULE_INIT, SSL_R_SSL_COMMAND_SECTION_EMPTY); ERR_add_error_data(4, "name=", sect->name, ", value=", sect->value); goto err; } ssl_name->name = BUF_strdup(sect->name); if (ssl_name->name == NULL) goto err; cnt = sk_CONF_VALUE_num(cmds); ssl_name->cmds = OPENSSL_zalloc(cnt * sizeof(struct ssl_conf_cmd)); if (ssl_name->cmds == NULL) goto err; ssl_name->cmd_count = cnt; for (j = 0; j < cnt; j++) { const char *name; CONF_VALUE *cmd_conf = sk_CONF_VALUE_value(cmds, j); struct ssl_conf_cmd *cmd = ssl_name->cmds + j; /* Skip any initial dot in name */ name = strchr(cmd_conf->name, '.'); if (name != NULL) name++; else name = cmd_conf->name; cmd->cmd = BUF_strdup(name); cmd->arg = BUF_strdup(cmd_conf->value); if (cmd->cmd == NULL || cmd->arg == NULL) goto err; } } rv = 1; err: if (rv == 0) ssl_module_free(md); return rv; }
static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret=1; FILE *fp=(FILE *)b->ptr; FILE **fpp; char p[4]; switch (cmd) { case BIO_C_FILE_SEEK: case BIO_CTRL_RESET: ret=(long)fseek(fp,num,0); break; case BIO_CTRL_EOF: ret=(long)feof(fp); break; case BIO_C_FILE_TELL: case BIO_CTRL_INFO: ret=ftell(fp); break; case BIO_C_SET_FILE_PTR: file_free(b); b->shutdown=(int)num&BIO_CLOSE; b->ptr=(char *)ptr; b->init=1; #if defined(OPENSSL_SYS_WINDOWS) if (num & BIO_FP_TEXT) _setmode(fileno((FILE *)ptr),_O_TEXT); else _setmode(fileno((FILE *)ptr),_O_BINARY); #elif defined(OPENSSL_SYS_MSDOS) { int fd = fileno((FILE*)ptr); /* Set correct text/binary mode */ if (num & BIO_FP_TEXT) _setmode(fd,_O_TEXT); /* Dangerous to set stdin/stdout to raw (unless redirected) */ else { if (fd == STDIN_FILENO || fd == STDOUT_FILENO) { if (isatty(fd) <= 0) _setmode(fd,_O_BINARY); } else _setmode(fd,_O_BINARY); } } #elif defined(OPENSSL_SYS_OS2) if (num & BIO_FP_TEXT) setmode(fileno((FILE *)ptr), O_TEXT); else setmode(fileno((FILE *)ptr), O_BINARY); #endif break; case BIO_C_SET_FILENAME: file_free(b); b->shutdown=(int)num&BIO_CLOSE; if (num & BIO_FP_APPEND) { if (num & BIO_FP_READ) BUF_strlcpy(p,"a+",sizeof p); else BUF_strlcpy(p,"a",sizeof p); } else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) BUF_strlcpy(p,"r+",sizeof p); else if (num & BIO_FP_WRITE) BUF_strlcpy(p,"w",sizeof p); else if (num & BIO_FP_READ) BUF_strlcpy(p,"r",sizeof p); else { BIOerr(BIO_F_FILE_CTRL,BIO_R_BAD_FOPEN_MODE); ret=0; break; } #if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_OS2) if (!(num & BIO_FP_TEXT)) strcat(p,"b"); else strcat(p,"t"); #endif fp=fopen(ptr,p); if (fp == NULL) { SYSerr(SYS_F_FOPEN,get_last_sys_error()); ERR_add_error_data(5,"fopen('",ptr,"','",p,"')"); BIOerr(BIO_F_FILE_CTRL,ERR_R_SYS_LIB); ret=0; break; } b->ptr=(char *)fp; b->init=1; break; case BIO_C_GET_FILE_PTR: /* the ptr parameter is actually a FILE ** in this case. */ if (ptr != NULL) { fpp=(FILE **)ptr; *fpp=(FILE *)b->ptr; } break; case BIO_CTRL_GET_CLOSE: ret=(long)b->shutdown; break; case BIO_CTRL_SET_CLOSE: b->shutdown=(int)num; break; case BIO_CTRL_FLUSH: fflush((FILE *)b->ptr); break; case BIO_CTRL_DUP: ret=1; break; case BIO_CTRL_WPENDING: case BIO_CTRL_PENDING: case BIO_CTRL_PUSH: case BIO_CTRL_POP: default: ret=0; break; } return(ret); }
static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key) { unsigned char *pubkey = NULL; DWORD len; BLOBHEADER *bh; RSA *rkey = NULL; DSA *dkey = NULL; EVP_PKEY *ret = NULL; if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len)) { CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR); capi_addlasterror(); return NULL; } pubkey = OPENSSL_malloc(len); if (!pubkey) goto memerr; if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len)) { CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR); capi_addlasterror(); goto err; } bh = (BLOBHEADER *)pubkey; if (bh->bType != PUBLICKEYBLOB) { CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB); goto err; } if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX) { RSAPUBKEY *rp; DWORD rsa_modlen; unsigned char *rsa_modulus; rp = (RSAPUBKEY *)(bh + 1); if (rp->magic != 0x31415352) { char magstr[10]; BIO_snprintf(magstr, 10, "%lx", rp->magic); CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); ERR_add_error_data(2, "magic=0x", magstr); goto err; } rsa_modulus = (unsigned char *)(rp + 1); rkey = RSA_new_method(eng); if (!rkey) goto memerr; rkey->e = BN_new(); rkey->n = BN_new(); if (!rkey->e || !rkey->n) goto memerr; if (!BN_set_word(rkey->e, rp->pubexp)) goto memerr; rsa_modlen = rp->bitlen / 8; if (!lend_tobn(rkey->n, rsa_modulus, rsa_modlen)) goto memerr; RSA_set_ex_data(rkey, rsa_capi_idx, key); if (!(ret = EVP_PKEY_new())) goto memerr; EVP_PKEY_assign_RSA(ret, rkey); rkey = NULL; } else if (bh->aiKeyAlg == CALG_DSS_SIGN) { DSSPUBKEY *dp; DWORD dsa_plen; unsigned char *btmp; dp = (DSSPUBKEY *)(bh + 1); if (dp->magic != 0x31535344) { char magstr[10]; BIO_snprintf(magstr, 10, "%lx", dp->magic); CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER); ERR_add_error_data(2, "magic=0x", magstr); goto err; } dsa_plen = dp->bitlen / 8; btmp = (unsigned char *)(dp + 1); dkey = DSA_new_method(eng); if (!dkey) goto memerr; dkey->p = BN_new(); dkey->q = BN_new(); dkey->g = BN_new(); dkey->pub_key = BN_new(); if (!dkey->p || !dkey->q || !dkey->g || !dkey->pub_key) goto memerr; if (!lend_tobn(dkey->p, btmp, dsa_plen)) goto memerr; btmp += dsa_plen; if (!lend_tobn(dkey->q, btmp, 20)) goto memerr; btmp += 20; if (!lend_tobn(dkey->g, btmp, dsa_plen)) goto memerr; btmp += dsa_plen; if (!lend_tobn(dkey->pub_key, btmp, dsa_plen)) goto memerr; btmp += dsa_plen; DSA_set_ex_data(dkey, dsa_capi_idx, key); if (!(ret = EVP_PKEY_new())) goto memerr; EVP_PKEY_assign_DSA(ret, dkey); dkey = NULL; } else { char algstr[10]; BIO_snprintf(algstr, 10, "%lx", bh->aiKeyAlg); CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM); ERR_add_error_data(2, "aiKeyAlg=0x", algstr); goto err; } err: if (pubkey) OPENSSL_free(pubkey); if (!ret) { if (rkey) RSA_free(rkey); if (dkey) DSA_free(dkey); } return ret; memerr: CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE); goto err; }
int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, const RSA *rsa) { ALG_ID alg; HCRYPTHASH hash; DWORD slen; unsigned int i; int ret = -1; CAPI_KEY *capi_key; CAPI_CTX *ctx; ctx = ENGINE_get_ex_data(rsa->engine, capi_idx); CAPI_trace(ctx, "Called CAPI_rsa_sign()\n"); capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); if (!capi_key) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY); return -1; } /* Convert the signature type to a CryptoAPI algorithm ID */ switch(dtype) { case NID_sha1: alg = CALG_SHA1; break; case NID_md5: alg = CALG_MD5; break; case NID_md5_sha1: alg = CALG_SSL3_SHAMD5; break; default: { char algstr[10]; BIO_snprintf(algstr, 10, "%lx", dtype); CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID); ERR_add_error_data(2, "NID=0x", algstr); return -1; } } /* Create the hash object */ if(!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT); capi_addlasterror(); return -1; } /* Set the hash value to the value passed */ if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE); capi_addlasterror(); goto err; } /* Finally sign it */ slen = RSA_size(rsa); if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH); capi_addlasterror(); goto err; } else { ret = 1; /* Inplace byte reversal of signature */ for(i = 0; i < slen / 2; i++) { unsigned char c; c = sigret[i]; sigret[i] = sigret[slen - i - 1]; sigret[slen - i - 1] = c; } *siglen = slen; } /* Now cleanup */ err: CryptDestroyHash(hash); return ret; }
static void capi_adderror(DWORD err) { char errstr[10]; BIO_snprintf(errstr, 10, "%lX", err); ERR_add_error_data(2, "Error code= 0x", errstr); }
/*- * BIO_lookup - look up the node and service you want to connect to. * @node: the node you want to connect to. * @service: the service you want to connect to. * @lookup_type: declare intent with the result, client or server. * @family: the address family you want to use. Use AF_UNSPEC for any, or * AF_INET, AF_INET6 or AF_UNIX. * @socktype: The socket type you want to use. Can be SOCK_STREAM, SOCK_DGRAM * or 0 for all. * @res: Storage place for the resulting list of returned addresses * * This will do a lookup of the node and service that you want to connect to. * It returns a linked list of different addresses you can try to connect to. * * When no longer needed you should call BIO_ADDRINFO_free() to free the result. * * The return value is 1 on success or 0 in case of error. */ int BIO_lookup(const char *host, const char *service, enum BIO_lookup_type lookup_type, int family, int socktype, BIO_ADDRINFO **res) { int ret = 0; /* Assume failure */ switch(family) { case AF_INET: #ifdef AF_INET6 case AF_INET6: #endif #ifdef AF_UNIX case AF_UNIX: #endif #ifdef AF_UNSPEC case AF_UNSPEC: #endif break; default: BIOerr(BIO_F_BIO_LOOKUP, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY); return 0; } #ifdef AF_UNIX if (family == AF_UNIX) { if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res)) return 1; else BIOerr(BIO_F_BIO_LOOKUP, ERR_R_MALLOC_FAILURE); return 0; } #endif if (BIO_sock_init() != 1) return 0; if (1) { int gai_ret = 0; #ifdef AI_PASSIVE struct addrinfo hints; memset(&hints, 0, sizeof hints); hints.ai_family = family; hints.ai_socktype = socktype; if (lookup_type == BIO_LOOKUP_SERVER) hints.ai_flags |= AI_PASSIVE; /* Note that |res| SHOULD be a 'struct addrinfo **' thanks to * macro magic in bio_lcl.h */ switch ((gai_ret = getaddrinfo(host, service, &hints, res))) { # ifdef EAI_SYSTEM case EAI_SYSTEM: SYSerr(SYS_F_GETADDRINFO, get_last_socket_error()); BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB); break; # endif case 0: ret = 1; /* Success */ break; default: BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB); ERR_add_error_data(1, gai_strerror(gai_ret)); break; } } else { #endif const struct hostent *he; /* * Because struct hostent is defined for 32-bit pointers only with * VMS C, we need to make sure that '&he_fallback_address' and * '&he_fallback_addresses' are 32-bit pointers */ #if defined(OPENSSL_SYS_VMS) && defined(__DECC) # pragma pointer_size save # pragma pointer_size 32 #endif /* Windows doesn't seem to have in_addr_t */ #ifdef OPENSSL_SYS_WINDOWS static uint32_t he_fallback_address; static const char *he_fallback_addresses[] = { (char *)&he_fallback_address, NULL }; #else static in_addr_t he_fallback_address; static const char *he_fallback_addresses[] = { (char *)&he_fallback_address, NULL }; #endif static const struct hostent he_fallback = { NULL, NULL, AF_INET, sizeof(he_fallback_address), (char **)&he_fallback_addresses }; #if defined(OPENSSL_SYS_VMS) && defined(__DECC) # pragma pointer_size restore #endif struct servent *se; /* Apparently, on WIN64, s_proto and s_port have traded places... */ #ifdef _WIN64 struct servent se_fallback = { NULL, NULL, NULL, 0 }; #else struct servent se_fallback = { NULL, NULL, 0, NULL }; #endif CRYPTO_THREAD_run_once(&bio_lookup_init, do_bio_lookup_init); CRYPTO_THREAD_write_lock(bio_lookup_lock); he_fallback_address = INADDR_ANY; if (host == NULL) { he = &he_fallback; switch(lookup_type) { case BIO_LOOKUP_CLIENT: he_fallback_address = INADDR_LOOPBACK; break; case BIO_LOOKUP_SERVER: he_fallback_address = INADDR_ANY; break; default: OPENSSL_assert(("We forgot to handle a lookup type!" == 0)); break; } } else { he = gethostbyname(host); if (he == NULL) { #ifndef OPENSSL_SYS_WINDOWS BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB); ERR_add_error_data(1, hstrerror(h_errno)); #else SYSerr(SYS_F_GETHOSTBYNAME, WSAGetLastError()); #endif ret = 0; goto err; } } if (service == NULL) { se_fallback.s_port = 0; se_fallback.s_proto = NULL; se = &se_fallback; } else { char *endp = NULL; long portnum = strtol(service, &endp, 10); /* * Because struct servent is defined for 32-bit pointers only with * VMS C, we need to make sure that 'proto' is a 32-bit pointer. */ #if defined(OPENSSL_SYS_VMS) && defined(__DECC) # pragma pointer_size save # pragma pointer_size 32 #endif char *proto = NULL; #if defined(OPENSSL_SYS_VMS) && defined(__DECC) # pragma pointer_size restore #endif switch (socktype) { case SOCK_STREAM: proto = "tcp"; break; case SOCK_DGRAM: proto = "udp"; break; } if (endp != service && *endp == '\0' && portnum > 0 && portnum < 65536) { se_fallback.s_port = htons(portnum); se_fallback.s_proto = proto; se = &se_fallback; } else if (endp == service) { se = getservbyname(service, proto); if (se == NULL) { #ifndef OPENSSL_SYS_WINDOWS BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB); ERR_add_error_data(1, hstrerror(h_errno)); #else SYSerr(SYS_F_GETSERVBYNAME, WSAGetLastError()); #endif goto err; } } else { BIOerr(BIO_F_BIO_LOOKUP, BIO_R_MALFORMED_HOST_OR_SERVICE); goto err; } } *res = NULL; { /* * Because hostent::h_addr_list is an array of 32-bit pointers with VMS C, * we must make sure our iterator designates the same element type, hence * the pointer size dance. */ #if defined(OPENSSL_SYS_VMS) && defined(__DECC) # pragma pointer_size save # pragma pointer_size 32 #endif char **addrlistp; #if defined(OPENSSL_SYS_VMS) && defined(__DECC) # pragma pointer_size restore #endif size_t addresses; BIO_ADDRINFO *tmp_bai = NULL; /* The easiest way to create a linked list from an array is to start from the back */ for(addrlistp = he->h_addr_list; *addrlistp != NULL; addrlistp++) ; for(addresses = addrlistp - he->h_addr_list; addrlistp--, addresses-- > 0; ) { if (!addrinfo_wrap(he->h_addrtype, socktype, *addrlistp, he->h_length, se->s_port, &tmp_bai)) goto addrinfo_malloc_err; tmp_bai->bai_next = *res; *res = tmp_bai; continue; addrinfo_malloc_err: BIO_ADDRINFO_free(*res); *res = NULL; BIOerr(BIO_F_BIO_LOOKUP, ERR_R_MALLOC_FAILURE); ret = 0; goto err; } ret = 1; } err: CRYPTO_THREAD_unlock(bio_lookup_lock); } return ret; }
/*- * addr_strings - helper function to get host and service names * @ap: the BIO_ADDR that has the input info * @numeric: 0 if actual names should be returned, 1 if the numeric * representation should be returned. * @hostname: a pointer to a pointer to a memory area to store the * host name or numeric representation. Unused if NULL. * @service: a pointer to a pointer to a memory area to store the * service name or numeric representation. Unused if NULL. * * The return value is 0 on failure, with the error code in the error * stack, and 1 on success. */ static int addr_strings(const BIO_ADDR *ap, int numeric, char **hostname, char **service) { if (BIO_sock_init() != 1) return 0; if (1) { #ifdef AI_PASSIVE int ret = 0; char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = ""; int flags = 0; if (numeric) flags |= NI_NUMERICHOST | NI_NUMERICSERV; if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap), BIO_ADDR_sockaddr_size(ap), host, sizeof(host), serv, sizeof(serv), flags)) != 0) { # ifdef EAI_SYSTEM if (ret == EAI_SYSTEM) { SYSerr(SYS_F_GETNAMEINFO, get_last_socket_error()); BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB); } else # endif { BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB); ERR_add_error_data(1, gai_strerror(ret)); } return 0; } /* VMS getnameinfo() has a bug, it doesn't fill in serv, which * leaves it with whatever garbage that happens to be there. * However, we initialise serv with the empty string (serv[0] * is therefore NUL), so it gets real easy to detect when things * didn't go the way one might expect. */ if (serv[0] == '\0') { BIO_snprintf(serv, sizeof(serv), "%d", ntohs(BIO_ADDR_rawport(ap))); } if (hostname != NULL) *hostname = OPENSSL_strdup(host); if (service != NULL) *service = OPENSSL_strdup(serv); } else { #endif if (hostname != NULL) *hostname = OPENSSL_strdup(inet_ntoa(ap->s_in.sin_addr)); if (service != NULL) { char serv[6]; /* port is 16 bits => max 5 decimal digits */ BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->s_in.sin_port)); *service = OPENSSL_strdup(serv); } } if ((hostname != NULL && *hostname == NULL) || (service != NULL && *service == NULL)) { if (hostname != NULL) { OPENSSL_free(*hostname); *hostname = NULL; } if (service != NULL) { OPENSSL_free(*service); *service = NULL; } BIOerr(BIO_F_ADDR_STRINGS, ERR_R_MALLOC_FAILURE); return 0; } return 1; }
/*- * Return up to 'len' payload bytes received in 'type' records. * 'type' is one of the following: * * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) * - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us) * - 0 (during a shutdown, no data has to be returned) * * If we don't have stored data to work from, read a SSL/TLS record first * (possibly multiple records if we still don't have anything to return). * * This function must handle any surprises the peer may have for us, such as * Alert records (e.g. close_notify) or renegotiation requests. ChangeCipherSpec * messages are treated as if they were handshake messages *if* the |recd_type| * argument is non NULL. * Also if record payloads contain fragments too small to process, we store * them until there is enough for the respective protocol (the record protocol * may use arbitrary fragmentation and even interleaving): * Change cipher spec protocol * just 1 byte needed, no need for keeping anything stored * Alert protocol * 2 bytes needed (AlertLevel, AlertDescription) * Handshake protocol * 4 bytes needed (HandshakeType, uint24 length) -- we just have * to detect unexpected Client Hello and Hello Request messages * here, anything else is handled by higher layers * Application data protocol * none of our business */ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, int len, int peek) { int al, i, j, ret; unsigned int n; SSL3_RECORD *rr; void (*cb) (const SSL *ssl, int type2, int val) = NULL; if (!SSL3_BUFFER_is_initialised(&s->rlayer.rbuf)) { /* Not initialized yet */ if (!ssl3_setup_buffers(s)) return (-1); } if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE)) || (peek && (type != SSL3_RT_APPLICATION_DATA))) { SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); return -1; } /* * check whether there's a handshake message (client hello?) waiting */ if ((ret = have_handshake_fragment(s, type, buf, len))) { *recvd_type = SSL3_RT_HANDSHAKE; return ret; } /* * Now s->rlayer.d->handshake_fragment_len == 0 if * type == SSL3_RT_HANDSHAKE. */ #ifndef OPENSSL_NO_SCTP /* * Continue handshake if it had to be interrupted to read app data with * SCTP. */ if ((!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) || (BIO_dgram_is_sctp(SSL_get_rbio(s)) && ossl_statem_in_sctp_read_sock(s) && s->s3->in_read_app_data != 2)) #else if (!ossl_statem_get_in_handshake(s) && SSL_in_init(s)) #endif { /* type == SSL3_RT_APPLICATION_DATA */ i = s->handshake_func(s); if (i < 0) return (i); if (i == 0) { SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE); return (-1); } } start: s->rwstate = SSL_NOTHING; /*- * s->s3->rrec.type - is the type of record * s->s3->rrec.data, - data * s->s3->rrec.off, - offset into 'data' for next read * s->s3->rrec.length, - number of bytes. */ rr = s->rlayer.rrec; /* * We are not handshaking and have no data yet, so process data buffered * during the last handshake in advance, if any. */ if (SSL_is_init_finished(s) && SSL3_RECORD_get_length(rr) == 0) { pitem *item; item = pqueue_pop(s->rlayer.d->buffered_app_data.q); if (item) { #ifndef OPENSSL_NO_SCTP /* Restore bio_dgram_sctp_rcvinfo struct */ if (BIO_dgram_is_sctp(SSL_get_rbio(s))) { DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data; BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO, sizeof(rdata->recordinfo), &rdata->recordinfo); } #endif dtls1_copy_record(s, item); OPENSSL_free(item->data); pitem_free(item); } } /* Check for timeout */ if (dtls1_handle_timeout(s) > 0) goto start; /* get new packet if necessary */ if ((SSL3_RECORD_get_length(rr) == 0) || (s->rlayer.rstate == SSL_ST_READ_BODY)) { ret = dtls1_get_record(s); if (ret <= 0) { ret = dtls1_read_failed(s, ret); /* anything other than a timeout is an error */ if (ret <= 0) return (ret); else goto start; } } /* * Reset the count of consecutive warning alerts if we've got a non-empty * record that isn't an alert. */ if (SSL3_RECORD_get_type(rr) != SSL3_RT_ALERT && SSL3_RECORD_get_length(rr) != 0) s->rlayer.alert_count = 0; /* we now have a packet which can be read and processed */ if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, * reset by ssl3_get_finished */ && (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE)) { /* * We now have application data between CCS and Finished. Most likely * the packets were reordered on their way, so buffer the application * data for later processing rather than dropping the connection. */ if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data), SSL3_RECORD_get_seq_num(rr)) < 0) { SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); return -1; } SSL3_RECORD_set_length(rr, 0); goto start; } /* * If the other end has shut down, throw anything we read away (even in * 'peek' mode) */ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { SSL3_RECORD_set_length(rr, 0); s->rwstate = SSL_NOTHING; return (0); } if (type == SSL3_RECORD_get_type(rr) || (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC && type == SSL3_RT_HANDSHAKE && recvd_type != NULL)) { /* * SSL3_RT_APPLICATION_DATA or * SSL3_RT_HANDSHAKE or * SSL3_RT_CHANGE_CIPHER_SPEC */ /* * make sure that we are not getting application data when we are * doing a handshake for the first time */ if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) && (s->enc_read_ctx == NULL)) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_APP_DATA_IN_HANDSHAKE); goto f_err; } if (recvd_type != NULL) *recvd_type = SSL3_RECORD_get_type(rr); if (len <= 0) return (len); if ((unsigned int)len > SSL3_RECORD_get_length(rr)) n = SSL3_RECORD_get_length(rr); else n = (unsigned int)len; memcpy(buf, &(SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]), n); if (!peek) { SSL3_RECORD_sub_length(rr, n); SSL3_RECORD_add_off(rr, n); if (SSL3_RECORD_get_length(rr) == 0) { s->rlayer.rstate = SSL_ST_READ_HEADER; SSL3_RECORD_set_off(rr, 0); } } #ifndef OPENSSL_NO_SCTP /* * We were about to renegotiate but had to read belated application * data first, so retry. */ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA && ossl_statem_in_sctp_read_sock(s)) { s->rwstate = SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); } /* * We might had to delay a close_notify alert because of reordered * app data. If there was an alert and there is no message to read * anymore, finally set shutdown. */ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && s->d1->shutdown_received && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { s->shutdown |= SSL_RECEIVED_SHUTDOWN; return (0); } #endif return (n); } /* * If we get here, then type != rr->type; if we have a handshake message, * then it was unexpected (Hello Request or Client Hello). */ /* * In case of record types for which we have 'fragment' storage, fill * that so that we can process the data at a fixed place. */ { unsigned int k, dest_maxlen = 0; unsigned char *dest = NULL; unsigned int *dest_len = NULL; if (SSL3_RECORD_get_type(rr) == SSL3_RT_HANDSHAKE) { dest_maxlen = sizeof s->rlayer.d->handshake_fragment; dest = s->rlayer.d->handshake_fragment; dest_len = &s->rlayer.d->handshake_fragment_len; } else if (SSL3_RECORD_get_type(rr) == SSL3_RT_ALERT) { dest_maxlen = sizeof(s->rlayer.d->alert_fragment); dest = s->rlayer.d->alert_fragment; dest_len = &s->rlayer.d->alert_fragment_len; } #ifndef OPENSSL_NO_HEARTBEATS else if (SSL3_RECORD_get_type(rr) == DTLS1_RT_HEARTBEAT) { /* We allow a 0 return */ if (dtls1_process_heartbeat(s, SSL3_RECORD_get_data(rr), SSL3_RECORD_get_length(rr)) < 0) { return -1; } /* Exit and notify application to read again */ SSL3_RECORD_set_length(rr, 0); s->rwstate = SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); return (-1); } #endif /* else it's a CCS message, or application data or wrong */ else if (SSL3_RECORD_get_type(rr) != SSL3_RT_CHANGE_CIPHER_SPEC) { /* * Application data while renegotiating is allowed. Try again * reading. */ if (SSL3_RECORD_get_type(rr) == SSL3_RT_APPLICATION_DATA) { BIO *bio; s->s3->in_read_app_data = 2; bio = SSL_get_rbio(s); s->rwstate = SSL_READING; BIO_clear_retry_flags(bio); BIO_set_retry_read(bio); return (-1); } /* Not certain if this is the right error handling */ al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD); goto f_err; } if (dest_maxlen > 0) { /* * XDTLS: In a pathological case, the Client Hello may be * fragmented--don't always expect dest_maxlen bytes */ if (SSL3_RECORD_get_length(rr) < dest_maxlen) { #ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE /* * for normal alerts rr->length is 2, while * dest_maxlen is 7 if we were to handle this * non-existing alert... */ FIX ME; #endif s->rlayer.rstate = SSL_ST_READ_HEADER; SSL3_RECORD_set_length(rr, 0); goto start; } /* now move 'n' bytes: */ for (k = 0; k < dest_maxlen; k++) { dest[k] = SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)]; SSL3_RECORD_add_off(rr, 1); SSL3_RECORD_add_length(rr, -1); } *dest_len = dest_maxlen; } } /*- * s->rlayer.d->handshake_fragment_len == 12 iff rr->type == SSL3_RT_HANDSHAKE; * s->rlayer.d->alert_fragment_len == 7 iff rr->type == SSL3_RT_ALERT. * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */ /* If we are a client, check for an incoming 'Hello Request': */ if ((!s->server) && (s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) && (s->rlayer.d->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) && (s->session != NULL) && (s->session->cipher != NULL)) { s->rlayer.d->handshake_fragment_len = 0; if ((s->rlayer.d->handshake_fragment[1] != 0) || (s->rlayer.d->handshake_fragment[2] != 0) || (s->rlayer.d->handshake_fragment[3] != 0)) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST); goto f_err; } /* * no need to check sequence number on HELLO REQUEST messages */ if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->rlayer.d->handshake_fragment, 4, s, s->msg_callback_arg); if (SSL_is_init_finished(s) && !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && !s->s3->renegotiate) { s->d1->handshake_read_seq++; s->new_session = 1; ssl3_renegotiate(s); if (ssl3_renegotiate_check(s)) { i = s->handshake_func(s); if (i < 0) return (i); if (i == 0) { SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE); return (-1); } if (!(s->mode & SSL_MODE_AUTO_RETRY)) { if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) { /* no read-ahead left? */ BIO *bio; /* * In the case where we try to read application data, * but we trigger an SSL handshake, we return -1 with * the retry option set. Otherwise renegotiation may * cause nasty problems in the blocking world */ s->rwstate = SSL_READING; bio = SSL_get_rbio(s); BIO_clear_retry_flags(bio); BIO_set_retry_read(bio); return (-1); } } } } /* * we either finished a handshake or ignored the request, now try * again to obtain the (application) data we were asked for */ goto start; } if (s->rlayer.d->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) { int alert_level = s->rlayer.d->alert_fragment[0]; int alert_descr = s->rlayer.d->alert_fragment[1]; s->rlayer.d->alert_fragment_len = 0; if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_ALERT, s->rlayer.d->alert_fragment, 2, s, s->msg_callback_arg); if (s->info_callback != NULL) cb = s->info_callback; else if (s->ctx->info_callback != NULL) cb = s->ctx->info_callback; if (cb != NULL) { j = (alert_level << 8) | alert_descr; cb(s, SSL_CB_READ_ALERT, j); } if (alert_level == SSL3_AL_WARNING) { s->s3->warn_alert = alert_descr; s->rlayer.alert_count++; if (s->rlayer.alert_count == MAX_WARN_ALERT_COUNT) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS); goto f_err; } if (alert_descr == SSL_AD_CLOSE_NOTIFY) { #ifndef OPENSSL_NO_SCTP /* * With SCTP and streams the socket may deliver app data * after a close_notify alert. We have to check this first so * that nothing gets discarded. */ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { s->d1->shutdown_received = 1; s->rwstate = SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); return -1; } #endif s->shutdown |= SSL_RECEIVED_SHUTDOWN; return (0); } #if 0 /* XXX: this is a possible improvement in the future */ /* now check if it's a missing record */ if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) { unsigned short seq; unsigned int frag_off; unsigned char *p = &(s->rlayer.d->alert_fragment[2]); n2s(p, seq); n2l3(p, frag_off); dtls1_retransmit_message(s, dtls1_get_queue_priority (frag->msg_header.seq, 0), frag_off, &found); if (!found && SSL_in_init(s)) { /* * fprintf( stderr,"in init = %d\n", SSL_in_init(s)); */ /* * requested a message not yet sent, send an alert * ourselves */ ssl3_send_alert(s, SSL3_AL_WARNING, DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); } } #endif } else if (alert_level == SSL3_AL_FATAL) { char tmp[16]; s->rwstate = SSL_NOTHING; s->s3->fatal_alert = alert_descr; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr); BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr); ERR_add_error_data(2, "SSL alert number ", tmp); s->shutdown |= SSL_RECEIVED_SHUTDOWN; SSL_CTX_remove_session(s->session_ctx, s->session); return (0); } else { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNKNOWN_ALERT_TYPE); goto f_err; } goto start; } if (s->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a * shutdown */ s->rwstate = SSL_NOTHING; SSL3_RECORD_set_length(rr, 0); return (0); } if (SSL3_RECORD_get_type(rr) == SSL3_RT_CHANGE_CIPHER_SPEC) { /* * We can't process a CCS now, because previous handshake messages * are still missing, so just drop it. */ SSL3_RECORD_set_length(rr, 0); goto start; } /* * Unexpected handshake message (Client Hello, or protocol violation) */ if ((s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) && !ossl_statem_get_in_handshake(s)) { struct hm_header_st msg_hdr; /* this may just be a stale retransmit */ dtls1_get_message_header(rr->data, &msg_hdr); if (SSL3_RECORD_get_epoch(rr) != s->rlayer.d->r_epoch) { SSL3_RECORD_set_length(rr, 0); goto start; } /* * If we are server, we may have a repeated FINISHED of the client * here, then retransmit our CCS and FINISHED. */ if (msg_hdr.type == SSL3_MT_FINISHED) { if (dtls1_check_timeout_num(s) < 0) return -1; dtls1_retransmit_buffered_messages(s); SSL3_RECORD_set_length(rr, 0); goto start; } if (SSL_is_init_finished(s) && !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { ossl_statem_set_in_init(s, 1); s->renegotiate = 1; s->new_session = 1; } i = s->handshake_func(s); if (i < 0) return (i); if (i == 0) { SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE); return (-1); } if (!(s->mode & SSL_MODE_AUTO_RETRY)) { if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) { /* no read-ahead left? */ BIO *bio; /* * In the case where we try to read application data, but we * trigger an SSL handshake, we return -1 with the retry * option set. Otherwise renegotiation may cause nasty * problems in the blocking world */ s->rwstate = SSL_READING; bio = SSL_get_rbio(s); BIO_clear_retry_flags(bio); BIO_set_retry_read(bio); return (-1); } } goto start; } switch (SSL3_RECORD_get_type(rr)) { default: /* TLS just ignores unknown message types */ if (s->version == TLS1_VERSION) { SSL3_RECORD_set_length(rr, 0); goto start; } al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD); goto f_err; case SSL3_RT_CHANGE_CIPHER_SPEC: case SSL3_RT_ALERT: case SSL3_RT_HANDSHAKE: /* * we already handled all of these, with the possible exception of * SSL3_RT_HANDSHAKE when ossl_statem_get_in_handshake(s) is true, but * that should not happen when type != rr->type */ al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR); goto f_err; case SSL3_RT_APPLICATION_DATA: /* * At this point, we were expecting handshake data, but have * application data. If the library was running inside ssl3_read() * (i.e. in_read_app_data is set) and it makes sense to read * application data at this point (session renegotiation not yet * started), we will indulge it. */ if (s->s3->in_read_app_data && (s->s3->total_renegotiations != 0) && ossl_statem_app_data_allowed(s)) { s->s3->in_read_app_data = 2; return (-1); } else { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD); goto f_err; } } /* not reached */ f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); return (-1); }
static int conn_state(BIO *b, BIO_CONNECT *c) { int ret= -1,i; unsigned long l; char *p,*q; int (*cb)()=NULL; if (c->info_callback != NULL) cb=c->info_callback; for (;;) { switch (c->state) { case BIO_CONN_S_BEFORE: p=c->param_hostname; if (p == NULL) { BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTNAME_SPECIFIED); goto exit_loop; } for ( ; *p != '\0'; p++) { if ((*p == ':') || (*p == '/')) break; } i= *p; if ((i == ':') || (i == '/')) { *(p++)='\0'; if (i == ':') { for (q=p; *q; q++) if (*q == '/') { *q='\0'; break; } if (c->param_port != NULL) OPENSSL_free(c->param_port); c->param_port=BUF_strdup(p); } } if (c->param_port == NULL) { BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED); ERR_add_error_data(2,"host=",c->param_hostname); goto exit_loop; } c->state=BIO_CONN_S_GET_IP; break; case BIO_CONN_S_GET_IP: if (BIO_get_host_ip(c->param_hostname,&(c->ip[0])) <= 0) goto exit_loop; c->state=BIO_CONN_S_GET_PORT; break; case BIO_CONN_S_GET_PORT: if (c->param_port == NULL) { /* abort(); */ goto exit_loop; } else if (BIO_get_port(c->param_port,&c->port) <= 0) goto exit_loop; c->state=BIO_CONN_S_CREATE_SOCKET; break; case BIO_CONN_S_CREATE_SOCKET: /* now setup address */ memset((char *)&c->them,0,sizeof(c->them)); c->them.sin_family=AF_INET; c->them.sin_port=htons((unsigned short)c->port); l=(unsigned long) ((unsigned long)c->ip[0]<<24L)| ((unsigned long)c->ip[1]<<16L)| ((unsigned long)c->ip[2]<< 8L)| ((unsigned long)c->ip[3]); c->them.sin_addr.s_addr=htonl(l); c->state=BIO_CONN_S_CREATE_SOCKET; ret=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); if (ret == INVALID_SOCKET) { SYSerr(SYS_F_SOCKET,get_last_socket_error()); ERR_add_error_data(4,"host=",c->param_hostname, ":",c->param_port); BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET); goto exit_loop; } b->num=ret; c->state=BIO_CONN_S_NBIO; break; case BIO_CONN_S_NBIO: if (c->nbio) { if (!BIO_socket_nbio(b->num,1)) { BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO); ERR_add_error_data(4,"host=", c->param_hostname, ":",c->param_port); goto exit_loop; } } c->state=BIO_CONN_S_CONNECT; #if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE) i=1; i=setsockopt(b->num,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); if (i < 0) { SYSerr(SYS_F_SOCKET,get_last_socket_error()); ERR_add_error_data(4,"host=",c->param_hostname, ":",c->param_port); BIOerr(BIO_F_CONN_STATE,BIO_R_KEEPALIVE); goto exit_loop; } #endif break; case BIO_CONN_S_CONNECT: BIO_clear_retry_flags(b); ret=connect(b->num, (struct sockaddr *)&c->them, sizeof(c->them)); b->retry_reason=0; if (ret < 0) { if (BIO_sock_should_retry(ret)) { BIO_set_retry_special(b); c->state=BIO_CONN_S_BLOCKED_CONNECT; b->retry_reason=BIO_RR_CONNECT; } else { SYSerr(SYS_F_CONNECT,get_last_socket_error()); ERR_add_error_data(4,"host=", c->param_hostname, ":",c->param_port); BIOerr(BIO_F_CONN_STATE,BIO_R_CONNECT_ERROR); } goto exit_loop; } else c->state=BIO_CONN_S_OK; break; case BIO_CONN_S_BLOCKED_CONNECT: i=BIO_sock_error(b->num); if (i) { BIO_clear_retry_flags(b); SYSerr(SYS_F_CONNECT,i); ERR_add_error_data(4,"host=", c->param_hostname, ":",c->param_port); BIOerr(BIO_F_CONN_STATE,BIO_R_NBIO_CONNECT_ERROR); ret=0; goto exit_loop; } else c->state=BIO_CONN_S_OK; break; case BIO_CONN_S_OK: ret=1; goto exit_loop; default: /* abort(); */ goto exit_loop; } if (cb != NULL) { if (!(ret=cb((BIO *)b,c->state,ret))) goto end; } } /* Loop does not exit */ exit_loop: if (cb != NULL) ret=cb((BIO *)b,c->state,ret); end: return(ret); }
static int def_load_bio(CONF *conf, BIO *in, long *line) { /* The macro BUFSIZE conflicts with a system macro in VxWorks */ #define CONFBUFSIZE 512 int bufnum = 0, i, ii; BUF_MEM *buff = NULL; char *s, *p, *end; int again; long eline = 0; char btmp[DECIMAL_SIZE(eline) + 1]; CONF_VALUE *v = NULL, *tv; CONF_VALUE *sv = NULL; char *section = NULL, *buf; char *start, *psection, *pname; void *h = (void *)(conf->data); if ((buff = BUF_MEM_new()) == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB); goto err; } section = OPENSSL_strdup("default"); if (section == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } if (_CONF_new_data(conf) == 0) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } sv = _CONF_new_section(conf, section); if (sv == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); goto err; } bufnum = 0; again = 0; for (;;) { if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB); goto err; } p = &(buff->data[bufnum]); *p = '\0'; BIO_gets(in, p, CONFBUFSIZE - 1); p[CONFBUFSIZE - 1] = '\0'; ii = i = strlen(p); if (i == 0 && !again) break; again = 0; while (i > 0) { if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) break; else i--; } /* * we removed some trailing stuff so there is a new line on the end. */ if (ii && i == ii) again = 1; /* long line */ else { p[i] = '\0'; eline++; /* another input line */ } /* we now have a line with trailing \r\n removed */ /* i is the number of bytes */ bufnum += i; v = NULL; /* check for line continuation */ if (bufnum >= 1) { /* * If we have bytes and the last char '\\' and second last char * is not '\\' */ p = &(buff->data[bufnum - 1]); if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) { bufnum--; again = 1; } } if (again) continue; bufnum = 0; buf = buff->data; clear_comments(conf, buf); s = eat_ws(conf, buf); if (IS_EOF(conf, *s)) continue; /* blank line */ if (*s == '[') { char *ss; s++; start = eat_ws(conf, s); ss = start; again: end = eat_alpha_numeric(conf, ss); p = eat_ws(conf, end); if (*p != ']') { if (*p != '\0' && ss != p) { ss = p; goto again; } CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_CLOSE_SQUARE_BRACKET); goto err; } *end = '\0'; if (!str_copy(conf, NULL, §ion, start)) goto err; if ((sv = _CONF_get_section(conf, section)) == NULL) sv = _CONF_new_section(conf, section); if (sv == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); goto err; } continue; } else { pname = s; psection = NULL; end = eat_alpha_numeric(conf, s); if ((end[0] == ':') && (end[1] == ':')) { *end = '\0'; end += 2; psection = pname; pname = end; end = eat_alpha_numeric(conf, end); } p = eat_ws(conf, end); if (*p != '=') { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN); goto err; } *end = '\0'; p++; start = eat_ws(conf, p); while (!IS_EOF(conf, *p)) p++; p--; while ((p != start) && (IS_WS(conf, *p))) p--; p++; *p = '\0'; if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } if (psection == NULL) psection = section; v->name = OPENSSL_malloc(strlen(pname) + 1); v->value = NULL; if (v->name == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } OPENSSL_strlcpy(v->name, pname, strlen(pname) + 1); if (!str_copy(conf, psection, &(v->value), start)) goto err; if (strcmp(psection, section) != 0) { if ((tv = _CONF_get_section(conf, psection)) == NULL) tv = _CONF_new_section(conf, psection); if (tv == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); goto err; } } else tv = sv; if (_CONF_add_string(conf, tv, v) == 0) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } v = NULL; } } BUF_MEM_free(buff); OPENSSL_free(section); return (1); err: BUF_MEM_free(buff); OPENSSL_free(section); if (line != NULL) *line = eline; BIO_snprintf(btmp, sizeof(btmp), "%ld", eline); ERR_add_error_data(2, "line ", btmp); if (h != conf->data) { CONF_free(conf->data); conf->data = NULL; } if (v != NULL) { OPENSSL_free(v->name); OPENSSL_free(v->value); OPENSSL_free(v); } return (0); }
void vms_bind_sym(DSO *dso, const char *symname, void **sym) { DSO_VMS_INTERNAL *ptr; int status; #if 0 int flags = (1<<4); /* LIB$M_FIS_MIXEDCASE, but this symbol isn't defined in VMS older than 7.0 or so */ #else int flags = 0; #endif struct dsc$descriptor_s symname_dsc; *sym = NULL; symname_dsc.dsc$w_length = strlen(symname); symname_dsc.dsc$b_dtype = DSC$K_DTYPE_T; symname_dsc.dsc$b_class = DSC$K_CLASS_S; symname_dsc.dsc$a_pointer = (char *)symname; /* The cast is needed */ if((dso == NULL) || (symname == NULL)) { DSOerr(DSO_F_VMS_BIND_SYM,ERR_R_PASSED_NULL_PARAMETER); return; } if(sk_num(dso->meth_data) < 1) { DSOerr(DSO_F_VMS_BIND_SYM,DSO_R_STACK_ERROR); return; } ptr = (DSO_VMS_INTERNAL *)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1); if(ptr == NULL) { DSOerr(DSO_F_VMS_BIND_SYM,DSO_R_NULL_HANDLE); return; } if(dso->flags & DSO_FLAG_UPCASE_SYMBOL) flags = 0; status = do_find_symbol(ptr, &symname_dsc, sym, flags); if(!$VMS_STATUS_SUCCESS(status)) { unsigned short length; char errstring[257]; struct dsc$descriptor_s errstring_dsc; errstring_dsc.dsc$w_length = sizeof(errstring); errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T; errstring_dsc.dsc$b_class = DSC$K_CLASS_S; errstring_dsc.dsc$a_pointer = errstring; *sym = NULL; status = sys$getmsg(status, &length, &errstring_dsc, 1, 0); if (!$VMS_STATUS_SUCCESS(status)) lib$signal(status); /* This is really bad. Abort! */ else { errstring[length] = '\0'; DSOerr(DSO_F_VMS_BIND_SYM,DSO_R_SYM_FAILURE); if (ptr->imagename_dsc.dsc$w_length) ERR_add_error_data(9, "Symbol ", symname, " in ", ptr->filename, " (", ptr->imagename, ")", ": ", errstring); else ERR_add_error_data(6, "Symbol ", symname, " in ", ptr->filename, ": ", errstring); } return; } return; }
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) { EVP_PKEY *pkey = NULL; #ifndef OPENSSL_NO_RSA RSA *rsa = NULL; #endif #ifndef OPENSSL_NO_DSA DSA *dsa = NULL; ASN1_TYPE *t1, *t2; ASN1_INTEGER *privkey; STACK_OF(ASN1_TYPE) *ndsa = NULL; #endif #ifndef OPENSSL_NO_EC EC_KEY *eckey = NULL; const unsigned char *p_tmp; #endif #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC) ASN1_TYPE *param = NULL; BN_CTX *ctx = NULL; int plen; #endif X509_ALGOR *a; const unsigned char *p; const unsigned char *cp; int pkeylen; int nid; char obj_tmp[80]; if(p8->pkey->type == V_ASN1_OCTET_STRING) { p8->broken = PKCS8_OK; p = p8->pkey->value.octet_string->data; pkeylen = p8->pkey->value.octet_string->length; } else { p8->broken = PKCS8_NO_OCTET; p = p8->pkey->value.sequence->data; pkeylen = p8->pkey->value.sequence->length; } if (!(pkey = EVP_PKEY_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); return NULL; } a = p8->pkeyalg; nid = OBJ_obj2nid(a->algorithm); switch(nid) { #ifndef OPENSSL_NO_RSA case NID_rsaEncryption: cp = p; if (!(rsa = d2i_RSAPrivateKey (NULL,&cp, pkeylen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); return NULL; } EVP_PKEY_assign_RSA (pkey, rsa); break; #endif #ifndef OPENSSL_NO_DSA case NID_dsa: /* PKCS#8 DSA is weird: you just get a private key integer * and parameters in the AlgorithmIdentifier the pubkey must * be recalculated. */ /* Check for broken DSA PKCS#8, UGH! */ if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) { if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pkeylen, d2i_ASN1_TYPE, ASN1_TYPE_free))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } if(sk_ASN1_TYPE_num(ndsa) != 2 ) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } /* Handle Two broken types: * SEQUENCE {parameters, priv_key} * SEQUENCE {pub_key, priv_key} */ t1 = sk_ASN1_TYPE_value(ndsa, 0); t2 = sk_ASN1_TYPE_value(ndsa, 1); if(t1->type == V_ASN1_SEQUENCE) { p8->broken = PKCS8_EMBEDDED_PARAM; param = t1; } else if(a->parameter->type == V_ASN1_SEQUENCE) { p8->broken = PKCS8_NS_DB; param = a->parameter; } else { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } if(t2->type != V_ASN1_INTEGER) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } privkey = t2->value.integer; } else { if (!(privkey=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } param = p8->pkeyalg->parameter; } if (!param || (param->type != V_ASN1_SEQUENCE)) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } cp = p = param->value.sequence->data; plen = param->value.sequence->length; if (!(dsa = d2i_DSAparams (NULL, &cp, plen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto dsaerr; } /* We have parameters now set private key */ if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) { EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR); goto dsaerr; } /* Calculate public key (ouch!) */ if (!(dsa->pub_key = BN_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); goto dsaerr; } if (!(ctx = BN_CTX_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); goto dsaerr; } if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) { EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_PUBKEY_ERROR); goto dsaerr; } EVP_PKEY_assign_DSA(pkey, dsa); BN_CTX_free (ctx); if(ndsa) sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); else ASN1_INTEGER_free(privkey); break; dsaerr: BN_CTX_free (ctx); sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); DSA_free(dsa); EVP_PKEY_free(pkey); return NULL; break; #endif #ifndef OPENSSL_NO_EC case NID_X9_62_id_ecPublicKey: p_tmp = p; /* extract the ec parameters */ param = p8->pkeyalg->parameter; if (!param || ((param->type != V_ASN1_SEQUENCE) && (param->type != V_ASN1_OBJECT))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto ecerr; } if (param->type == V_ASN1_SEQUENCE) { cp = p = param->value.sequence->data; plen = param->value.sequence->length; if (!(eckey = d2i_ECParameters(NULL, &cp, plen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto ecerr; } } else { EC_GROUP *group; cp = p = param->value.object->data; plen = param->value.object->length; /* type == V_ASN1_OBJECT => the parameters are given * by an asn1 OID */ if ((eckey = EC_KEY_new()) == NULL) { EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_MALLOC_FAILURE); goto ecerr; } group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(a->parameter->value.object)); if (group == NULL) goto ecerr; EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); if (EC_KEY_set_group(eckey, group) == 0) goto ecerr; EC_GROUP_free(group); } /* We have parameters now set private key */ if (!d2i_ECPrivateKey(&eckey, &p_tmp, pkeylen)) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); goto ecerr; } /* calculate public key (if necessary) */ if (EC_KEY_get0_public_key(eckey) == NULL) { const BIGNUM *priv_key; const EC_GROUP *group; EC_POINT *pub_key; /* the public key was not included in the SEC1 private * key => calculate the public key */ group = EC_KEY_get0_group(eckey); pub_key = EC_POINT_new(group); if (pub_key == NULL) { EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { EC_POINT_free(pub_key); EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } priv_key = EC_KEY_get0_private_key(eckey); if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) { EC_POINT_free(pub_key); EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } if (EC_KEY_set_public_key(eckey, pub_key) == 0) { EC_POINT_free(pub_key); EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_EC_LIB); goto ecerr; } EC_POINT_free(pub_key); } EVP_PKEY_assign_EC_KEY(pkey, eckey); if (ctx) BN_CTX_free(ctx); break; ecerr: if (ctx) BN_CTX_free(ctx); if (eckey) EC_KEY_free(eckey); if (pkey) EVP_PKEY_free(pkey); return NULL; #endif default: EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); if (!a->algorithm) BUF_strlcpy (obj_tmp, "NULL", sizeof obj_tmp); else i2t_ASN1_OBJECT(obj_tmp, 80, a->algorithm); ERR_add_error_data(2, "TYPE=", obj_tmp); EVP_PKEY_free (pkey); return NULL; } return pkey; }
static char *vms_merger(DSO *dso, const char *filespec1, const char *filespec2) { int status; int filespec1len, filespec2len; struct FAB fab; #ifdef NAML$C_MAXRSS struct NAML nam; char esa[NAML$C_MAXRSS]; #else struct NAM nam; char esa[NAM$C_MAXRSS]; #endif char *merged; if (!filespec1) filespec1 = ""; if (!filespec2) filespec2 = ""; filespec1len = strlen(filespec1); filespec2len = strlen(filespec2); fab = cc$rms_fab; #ifdef NAML$C_MAXRSS nam = cc$rms_naml; #else nam = cc$rms_nam; #endif fab.fab$l_fna = (char *)filespec1; fab.fab$b_fns = filespec1len; fab.fab$l_dna = (char *)filespec2; fab.fab$b_dns = filespec2len; #ifdef NAML$C_MAXRSS if (filespec1len > NAM$C_MAXRSS) { fab.fab$l_fna = 0; fab.fab$b_fns = 0; nam.naml$l_long_filename = (char *)filespec1; nam.naml$l_long_filename_size = filespec1len; } if (filespec2len > NAM$C_MAXRSS) { fab.fab$l_dna = 0; fab.fab$b_dns = 0; nam.naml$l_long_defname = (char *)filespec2; nam.naml$l_long_defname_size = filespec2len; } nam.naml$l_esa = esa; nam.naml$b_ess = NAM$C_MAXRSS; nam.naml$l_long_expand = esa; nam.naml$l_long_expand_alloc = sizeof(esa); nam.naml$b_nop = NAM$M_SYNCHK | NAM$M_PWD; nam.naml$v_no_short_upcase = 1; fab.fab$l_naml = &nam; #else nam.nam$l_esa = esa; nam.nam$b_ess = NAM$C_MAXRSS; nam.nam$b_nop = NAM$M_SYNCHK | NAM$M_PWD; fab.fab$l_nam = &nam; #endif status = sys$parse(&fab, 0, 0); if(!$VMS_STATUS_SUCCESS(status)) { unsigned short length; char errstring[257]; struct dsc$descriptor_s errstring_dsc; errstring_dsc.dsc$w_length = sizeof(errstring); errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T; errstring_dsc.dsc$b_class = DSC$K_CLASS_S; errstring_dsc.dsc$a_pointer = errstring; status = sys$getmsg(status, &length, &errstring_dsc, 1, 0); if (!$VMS_STATUS_SUCCESS(status)) lib$signal(status); /* This is really bad. Abort! */ else { errstring[length] = '\0'; DSOerr(DSO_F_VMS_MERGER,DSO_R_FAILURE); ERR_add_error_data(7, "filespec \"", filespec1, "\", ", "defaults \"", filespec2, "\": ", errstring); } return(NULL); } #ifdef NAML$C_MAXRSS if (nam.naml$l_long_expand_size) { merged = OPENSSL_malloc(nam.naml$l_long_expand_size + 1); if(!merged) goto malloc_err; strncpy(merged, nam.naml$l_long_expand, nam.naml$l_long_expand_size); merged[nam.naml$l_long_expand_size] = '\0'; } else { merged = OPENSSL_malloc(nam.naml$b_esl + 1); if(!merged) goto malloc_err; strncpy(merged, nam.naml$l_esa, nam.naml$b_esl); merged[nam.naml$b_esl] = '\0'; } #else merged = OPENSSL_malloc(nam.nam$b_esl + 1); if(!merged) goto malloc_err; strncpy(merged, nam.nam$l_esa, nam.nam$b_esl); merged[nam.nam$b_esl] = '\0'; #endif return(merged); malloc_err: DSOerr(DSO_F_VMS_MERGER, ERR_R_MALLOC_FAILURE); }
int BIO_get_accept_socket(char *host, int bind_mode) { int ret=0; struct sockaddr_in server,client; int s=INVALID_SOCKET,cs; unsigned char ip[4]; unsigned short port; char *str=NULL,*e; const char *h,*p; unsigned long l; int err_num; if (BIO_sock_init() != 1) return(INVALID_SOCKET); if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET); h=p=NULL; h=str; for (e=str; *e; e++) { if (*e == ':') { p= &(e[1]); *e='\0'; } else if (*e == '/') { *e='\0'; break; } } if (p == NULL) { p=h; h="*"; } if (!BIO_get_port(p,&port)) goto err; memset((char *)&server,0,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(port); if (strcmp(h,"*") == 0) server.sin_addr.s_addr=INADDR_ANY; else { if (!BIO_get_host_ip(h,&(ip[0]))) goto err; l=(unsigned long) ((unsigned long)ip[0]<<24L)| ((unsigned long)ip[1]<<16L)| ((unsigned long)ip[2]<< 8L)| ((unsigned long)ip[3]); server.sin_addr.s_addr=htonl(l); } again: s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); if (s == INVALID_SOCKET) { SYSerr(SYS_F_SOCKET,get_last_socket_error()); ERR_add_error_data(3,"port='",host,"'"); BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET); goto err; } #ifdef SO_REUSEADDR if (bind_mode == BIO_BIND_REUSEADDR) { int i=1; ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i)); bind_mode=BIO_BIND_NORMAL; } #endif if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) { #ifdef SO_REUSEADDR err_num=get_last_socket_error(); if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && (err_num == EADDRINUSE)) { memcpy((char *)&client,(char *)&server,sizeof(server)); if (strcmp(h,"*") == 0) client.sin_addr.s_addr=htonl(0x7F000001); cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); if (cs != INVALID_SOCKET) { int ii; ii=connect(cs,(struct sockaddr *)&client, sizeof(client)); closesocket(cs); if (ii == INVALID_SOCKET) { bind_mode=BIO_BIND_REUSEADDR; closesocket(s); goto again; } /* else error */ } /* else error */ } #endif SYSerr(SYS_F_BIND,err_num); ERR_add_error_data(3,"port='",host,"'"); BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET); goto err; } enable_tcpcrypt(s); if (listen(s,MAX_LISTEN) == -1) { SYSerr(SYS_F_BIND,get_last_socket_error()); ERR_add_error_data(3,"port='",host,"'"); BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET); goto err; } ret=1; err: if (str != NULL) OPENSSL_free(str); if ((ret == 0) && (s != INVALID_SOCKET)) { closesocket(s); s= INVALID_SOCKET; } return(s); }
int bio_ber_get_header(BIO *bio, BIO_BER_CTX *ctx) { char buf[64]; int i,j,n; int ret; unsigned char *p; unsigned long length int tag; int class; long max; BIO_clear_retry_flags(b); /* Pack the buffer down if there is a hole at the front */ if (ctx->buf_off != 0) { p=ctx->buf; j=ctx->buf_off; n=ctx->buf_len-j; for (i=0; i<n; i++) { p[0]=p[j]; p++; } ctx->buf_len-j; ctx->buf_off=0; } /* If there is more room, read some more data */ i=BER_BUF_SIZE-ctx->buf_len; if (i) { i=BIO_read(bio->next_bio,&(ctx->buf[ctx->buf_len]),i); if (i <= 0) { BIO_copy_next_retry(b); return(i); } else ctx->buf_len+=i; } max=ctx->buf_len; p=ctx->buf; ret=ASN1_get_object(&p,&length,&tag,&class,max); if (ret & 0x80) { if ((ctx->buf_len < BER_BUF_SIZE) && (ERR_GET_REASON(ERR_peek_error()) == ASN1_R_TOO_LONG)) { ERR_clear_error(); /* clear the error */ BIO_set_retry_read(b); } return(-1); } /* We have no error, we have a header, so make use of it */ if ((ctx->tag >= 0) && (ctx->tag != tag)) { BIOerr(BIO_F_BIO_BER_GET_HEADER,BIO_R_TAG_MISMATCH); TINYCLR_SSL_SPRINTF(buf,"tag=%d, got %d",ctx->tag,tag); ERR_add_error_data(1,buf); return(-1); } if (ret & 0x01) if (ret & V_ASN1_CONSTRUCTED) }
static int parse_http_line1(char *line) { int retcode; char *p, *q, *r; /* Skip to first white space (passed protocol info) */ for(p = line; *p && !isspace((unsigned char)*p); p++) continue; if(!*p) { OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); return 0; } /* Skip past white space to start of response code */ while(*p && isspace((unsigned char)*p)) p++; if(!*p) { OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); return 0; } /* Find end of response code: first whitespace after start of code */ for(q = p; *q && !isspace((unsigned char)*q); q++) continue; if(!*q) { OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); return 0; } /* Set end of response code and start of message */ *q++ = 0; /* Attempt to parse numeric code */ retcode = strtoul(p, &r, 10); if(*r) return 0; /* Skip over any leading white space in message */ while(*q && isspace((unsigned char)*q)) q++; if(*q) { /* Finally zap any trailing white space in message (include * CRLF) */ /* We know q has a non white space character so this is OK */ for(r = q + strlen(q) - 1; isspace((unsigned char)*r); r--) *r = 0; } if(retcode != 200) { OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_ERROR); if(!*q) ERR_add_error_data(2, "Code=", p); else ERR_add_error_data(4, "Code=", p, ",Reason=", q); return 0; } return 1; }
static int asn1_cb(const char *elem, int len, void *bitstr) { tag_exp_arg *arg = bitstr; int i; int utype; int vlen = 0; const char *p, *vstart = NULL; int tmp_tag, tmp_class; if (elem == NULL) return 0; for(i = 0, p = elem; i < len; p++, i++) { /* Look for the ':' in name value pairs */ if (*p == ':') { vstart = p + 1; vlen = len - (vstart - elem); len = p - elem; break; } } utype = asn1_str2tag(elem, len); if (utype == -1) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_TAG); ERR_add_error_data(2, "tag=", elem); return -1; } /* If this is not a modifier mark end of string and exit */ if (!(utype & ASN1_GEN_FLAG)) { arg->utype = utype; arg->str = vstart; /* If no value and not end of string, error */ if (!vstart && elem[len]) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); return -1; } return 0; } switch(utype) { case ASN1_GEN_FLAG_IMP: /* Check for illegal multiple IMPLICIT tagging */ if (arg->imp_tag != -1) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING); return -1; } if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class)) return -1; break; case ASN1_GEN_FLAG_EXP: if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class)) return -1; if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0)) return -1; break; case ASN1_GEN_FLAG_SEQWRAP: if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1)) return -1; break; case ASN1_GEN_FLAG_SETWRAP: if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1)) return -1; break; case ASN1_GEN_FLAG_BITWRAP: if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1)) return -1; break; case ASN1_GEN_FLAG_OCTWRAP: if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1)) return -1; break; case ASN1_GEN_FLAG_FORMAT: if (!vstart) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); return -1; } if (!strncmp(vstart, "ASCII", 5)) arg->format = ASN1_GEN_FORMAT_ASCII; else if (!strncmp(vstart, "UTF8", 4)) arg->format = ASN1_GEN_FORMAT_UTF8; else if (!strncmp(vstart, "HEX", 3)) arg->format = ASN1_GEN_FORMAT_HEX; else if (!strncmp(vstart, "BITLIST", 7)) arg->format = ASN1_GEN_FORMAT_BITLIST; else { OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); return -1; } break; } return 1; }
static int int_engine_configure(char *name, char *value, const CONF *cnf) { int i; int ret = 0; long do_init = -1; STACK_OF(CONF_VALUE) *ecmds; CONF_VALUE *ecmd = NULL; char *ctrlname, *ctrlvalue; ENGINE *e = NULL; int soft = 0; name = skip_dot(name); #ifdef ENGINE_CONF_DEBUG fprintf(stderr, "Configuring engine %s\n", name); #endif /* Value is a section containing ENGINE commands */ ecmds = NCONF_get_section(cnf, value); if (!ecmds) { ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_ENGINE_SECTION_ERROR); return 0; } for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++) { ecmd = sk_CONF_VALUE_value(ecmds, i); ctrlname = skip_dot(ecmd->name); ctrlvalue = ecmd->value; #ifdef ENGINE_CONF_DEBUG fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname, ctrlvalue); #endif /* First handle some special pseudo ctrls */ /* Override engine name to use */ if (!op_strcmp(ctrlname, "engine_id")) name = ctrlvalue; else if (!strcmp(ctrlname, "soft_load")) soft = 1; /* Load a dynamic ENGINE */ else if (!op_strcmp(ctrlname, "dynamic_path")) { e = ENGINE_by_id("dynamic"); if (!e) goto err; if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0)) goto err; if (!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "2", 0)) goto err; if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) goto err; } /* ... add other pseudos here ... */ else { /* At this point we need an ENGINE structural reference * if we don't already have one. */ if (!e) { e = ENGINE_by_id(name); if (!e && soft) { ERR_clear_error(); return 1; } if (!e) goto err; } /* Allow "EMPTY" to mean no value: this allows a valid * "value" to be passed to ctrls of type NO_INPUT */ if (!op_strcmp(ctrlvalue, "EMPTY")) ctrlvalue = NULL; if (!op_strcmp(ctrlname, "init")) { if (!NCONF_get_number_e(cnf, value, "init", &do_init)) goto err; if (do_init == 1) { if (!int_engine_init(e)) goto err; } else if (do_init != 0) { ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_INVALID_INIT_VALUE); goto err; } } else if (!op_strcmp(ctrlname, "default_algorithms")) { if (!ENGINE_set_default_string(e, ctrlvalue)) goto err; } else if (!ENGINE_ctrl_cmd_string(e, ctrlname, ctrlvalue, 0)) goto err; } } if (e && (do_init == -1) && !int_engine_init(e)) { ecmd = NULL; goto err; } ret = 1; err: if (ret != 1) { ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_ENGINE_CONFIGURATION_ERROR); if (ecmd) ERR_add_error_data(6, "section=", ecmd->section, ", name=", ecmd->name, ", value=", ecmd->value); } if (e) ENGINE_free(e); return ret; }
static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) { ASN1_TYPE *atmp = NULL; CONF_VALUE vtmp; unsigned char *rdata; long rdlen; int no_unused = 1; if (!(atmp = ASN1_TYPE_new())) { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return NULL; } if (!str) str = ""; switch(utype) { case V_ASN1_NULL: if (str && *str) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL_VALUE); goto bad_form; } break; case V_ASN1_BOOLEAN: if (format != ASN1_GEN_FORMAT_ASCII) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ASCII_FORMAT); goto bad_form; } vtmp.name = NULL; vtmp.section = NULL; vtmp.value = (char *)str; if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BOOLEAN); goto bad_str; } break; case V_ASN1_INTEGER: case V_ASN1_ENUMERATED: if (format != ASN1_GEN_FORMAT_ASCII) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT); goto bad_form; } if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str))) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_INTEGER); goto bad_str; } break; case V_ASN1_OBJECT: if (format != ASN1_GEN_FORMAT_ASCII) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT); goto bad_form; } if (!(atmp->value.object = OBJ_txt2obj(str, 0))) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); goto bad_str; } break; case V_ASN1_UTCTIME: case V_ASN1_GENERALIZEDTIME: if (format != ASN1_GEN_FORMAT_ASCII) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT); goto bad_form; } if (!(atmp->value.asn1_string = ASN1_STRING_new())) { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); goto bad_str; } if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); goto bad_str; } atmp->value.asn1_string->type = utype; if (!ASN1_TIME_check(atmp->value.asn1_string)) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TIME_VALUE); goto bad_str; } break; case V_ASN1_BMPSTRING: case V_ASN1_PRINTABLESTRING: case V_ASN1_IA5STRING: case V_ASN1_T61STRING: case V_ASN1_UTF8STRING: case V_ASN1_VISIBLESTRING: case V_ASN1_UNIVERSALSTRING: case V_ASN1_GENERALSTRING: case V_ASN1_NUMERICSTRING: if (format == ASN1_GEN_FORMAT_ASCII) format = MBSTRING_ASC; else if (format == ASN1_GEN_FORMAT_UTF8) format = MBSTRING_UTF8; else { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_FORMAT); goto bad_form; } if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str, -1, format, ASN1_tag2bit(utype)) <= 0) { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); goto bad_str; } break; case V_ASN1_BIT_STRING: case V_ASN1_OCTET_STRING: if (!(atmp->value.asn1_string = ASN1_STRING_new())) { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); goto bad_form; } if (format == ASN1_GEN_FORMAT_HEX) { if (!(rdata = string_to_hex((char *)str, &rdlen))) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_HEX); goto bad_str; } atmp->value.asn1_string->data = rdata; atmp->value.asn1_string->length = rdlen; atmp->value.asn1_string->type = utype; } else if (format == ASN1_GEN_FORMAT_ASCII) ASN1_STRING_set(atmp->value.asn1_string, str, -1); else if ((format == ASN1_GEN_FORMAT_BITLIST) && (utype == V_ASN1_BIT_STRING)) { if (!CONF_parse_list(str, ',', 1, bitstr_cb, atmp->value.bit_string)) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_LIST_ERROR); goto bad_str; } no_unused = 0; } else { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT); goto bad_form; } if ((utype == V_ASN1_BIT_STRING) && no_unused) { atmp->value.asn1_string->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT; } break; default: OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_TYPE); goto bad_str; break; } atmp->type = utype; return atmp; bad_str: ERR_add_error_data(2, "string=", str); bad_form: ASN1_TYPE_free(atmp); return NULL; }
void vms_bind_sym(DSO *dso, const char *symname, void **sym) { DSO_VMS_INTERNAL *ptr; int status; # if 0 int flags = (1 << 4); /* LIB$M_FIS_MIXEDCASE, but this symbol isn't * defined in VMS older than 7.0 or so */ # else int flags = 0; # endif struct dsc$descriptor_s symname_dsc; /* Arrange 32-bit pointer to (copied) string storage, if needed. */ # if __INITIAL_POINTER_SIZE == 64 # define SYMNAME symname_32p # pragma pointer_size save # pragma pointer_size 32 char *symname_32p; # pragma pointer_size restore char symname_32[NAMX_MAXRSS + 1]; # else /* __INITIAL_POINTER_SIZE == 64 */ # define SYMNAME ((char *) symname) # endif /* __INITIAL_POINTER_SIZE == 64 [else] */ *sym = NULL; if ((dso == NULL) || (symname == NULL)) { DSOerr(DSO_F_VMS_BIND_SYM, ERR_R_PASSED_NULL_PARAMETER); return; } # if __INITIAL_POINTER_SIZE == 64 /* Copy the symbol name to storage with a 32-bit pointer. */ symname_32p = symname_32; strcpy(symname_32p, symname); # endif /* __INITIAL_POINTER_SIZE == 64 [else] */ symname_dsc.dsc$w_length = strlen(SYMNAME); symname_dsc.dsc$b_dtype = DSC$K_DTYPE_T; symname_dsc.dsc$b_class = DSC$K_CLASS_S; symname_dsc.dsc$a_pointer = SYMNAME; if (sk_void_num(dso->meth_data) < 1) { DSOerr(DSO_F_VMS_BIND_SYM, DSO_R_STACK_ERROR); return; } ptr = (DSO_VMS_INTERNAL *)sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1); if (ptr == NULL) { DSOerr(DSO_F_VMS_BIND_SYM, DSO_R_NULL_HANDLE); return; } if (dso->flags & DSO_FLAG_UPCASE_SYMBOL) flags = 0; status = do_find_symbol(ptr, &symname_dsc, sym, flags); if (!$VMS_STATUS_SUCCESS(status)) { unsigned short length; char errstring[257]; struct dsc$descriptor_s errstring_dsc; errstring_dsc.dsc$w_length = sizeof(errstring); errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T; errstring_dsc.dsc$b_class = DSC$K_CLASS_S; errstring_dsc.dsc$a_pointer = errstring; *sym = NULL; status = sys$getmsg(status, &length, &errstring_dsc, 1, 0); if (!$VMS_STATUS_SUCCESS(status)) lib$signal(status); /* This is really bad. Abort! */ else { errstring[length] = '\0'; DSOerr(DSO_F_VMS_BIND_SYM, DSO_R_SYM_FAILURE); if (ptr->imagename_dsc.dsc$w_length) ERR_add_error_data(9, "Symbol ", symname, " in ", ptr->filename, " (", ptr->imagename, ")", ": ", errstring); else ERR_add_error_data(6, "Symbol ", symname, " in ", ptr->filename, ": ", errstring); } return; } return; }
int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx) { const ASN1_TEMPLATE *tt, *errtt = NULL; const ASN1_COMPAT_FUNCS *cf; const ASN1_EXTERN_FUNCS *ef; const ASN1_AUX *aux = it->funcs; ASN1_aux_cb *asn1_cb; const unsigned char *p = NULL, *q; unsigned char *wp=NULL; /* BIG FAT WARNING! BREAKS CONST WHERE USED */ unsigned char imphack = 0, oclass; char seq_eoc, seq_nolen, cst, isopt; long tmplen; int i; int otag; int ret = 0; ASN1_VALUE *pchval, **pchptr, *ptmpval; if (!pval) return 0; if (aux && aux->asn1_cb) asn1_cb = aux->asn1_cb; else asn1_cb = 0; switch(it->itype) { case ASN1_ITYPE_PRIMITIVE: if (it->templates) { /* tagging or OPTIONAL is currently illegal on an item * template because the flags can't get passed down. * In practice this isn't a problem: we include the * relevant flags from the item template in the * template itself. */ if ((tag != -1) || opt) { ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); goto err; } return asn1_template_ex_d2i(pval, in, len, it->templates, opt, ctx); } return asn1_d2i_ex_primitive(pval, in, len, it, tag, aclass, opt, ctx); break; case ASN1_ITYPE_MSTRING: p = *in; /* Just read in tag and class */ ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, &p, len, -1, 0, 1, ctx); if (!ret) { ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); goto err; } /* Must be UNIVERSAL class */ if (oclass != V_ASN1_UNIVERSAL) { /* If OPTIONAL, assume this is OK */ if (opt) return -1; ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL); goto err; } /* Check tag matches bit map */ if (!(ASN1_tag2bit(otag) & it->utype)) { /* If OPTIONAL, assume this is OK */ if (opt) return -1; ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MSTRING_WRONG_TAG); goto err; } return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx); case ASN1_ITYPE_EXTERN: /* Use new style d2i */ ef = it->funcs; return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx); case ASN1_ITYPE_COMPAT: /* we must resort to old style evil hackery */ cf = it->funcs; /* If OPTIONAL see if it is there */ if (opt) { int exptag; p = *in; if (tag == -1) exptag = it->utype; else exptag = tag; /* Don't care about anything other than presence * of expected tag */ ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL, &p, len, exptag, aclass, 1, ctx); if (!ret) { ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); goto err; } if (ret == -1) return -1; } /* This is the old style evil hack IMPLICIT handling: * since the underlying code is expecting a tag and * class other than the one present we change the * buffer temporarily then change it back afterwards. * This doesn't and never did work for tags > 30. * * Yes this is *horrible* but it is only needed for * old style d2i which will hopefully not be around * for much longer. * FIXME: should copy the buffer then modify it so * the input buffer can be const: we should *always* * copy because the old style d2i might modify the * buffer. */ if (tag != -1) { wp = *(unsigned char **)in; imphack = *wp; if (p == NULL) { ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); goto err; } *wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED) | it->utype); } ptmpval = cf->asn1_d2i(pval, in, len); if (tag != -1) *wp = imphack; if (ptmpval) return 1; ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); goto err; case ASN1_ITYPE_CHOICE: if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it)) goto auxerr; /* Allocate structure */ if (!*pval && !ASN1_item_ex_new(pval, it)) { ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); goto err; } /* CHOICE type, try each possibility in turn */ pchval = NULL; p = *in; for (i = 0, tt=it->templates; i < it->tcount; i++, tt++) { pchptr = asn1_get_field_ptr(pval, tt); /* We mark field as OPTIONAL so its absence * can be recognised. */ ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx); /* If field not present, try the next one */ if (ret == -1) continue; /* If positive return, read OK, break loop */ if (ret > 0) break; /* Otherwise must be an ASN1 parsing error */ errtt = tt; ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); goto err; } /* Did we fall off the end without reading anything? */ if (i == it->tcount) { /* If OPTIONAL, this is OK */ if (opt) { /* Free and zero it */ ASN1_item_ex_free(pval, it); return -1; } ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE); goto err; } asn1_set_choice_selector(pval, i, it); *in = p; if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it)) goto auxerr; return 1; case ASN1_ITYPE_NDEF_SEQUENCE: case ASN1_ITYPE_SEQUENCE: p = *in; tmplen = len; /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ if (tag == -1) { tag = V_ASN1_SEQUENCE; aclass = V_ASN1_UNIVERSAL; } /* Get SEQUENCE length and update len, p */ ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, &p, len, tag, aclass, opt, ctx); if (!ret) { ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); goto err; } else if (ret == -1) return -1; if (aux && (aux->flags & ASN1_AFLG_BROKEN)) { len = tmplen - (p - *in); seq_nolen = 1; } /* If indefinite we don't do a length check */ else seq_nolen = seq_eoc; if (!cst) { ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); goto err; } if (!*pval && !ASN1_item_ex_new(pval, it)) { ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); goto err; } if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it)) goto auxerr; /* Get each field entry */ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { const ASN1_TEMPLATE *seqtt; ASN1_VALUE **pseqval; seqtt = asn1_do_adb(pval, tt, 1); if (!seqtt) goto err; pseqval = asn1_get_field_ptr(pval, seqtt); /* Have we ran out of data? */ if (!len) break; q = p; if (asn1_check_eoc(&p, len)) { if (!seq_eoc) { ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_UNEXPECTED_EOC); goto err; } len -= p - q; seq_eoc = 0; q = p; break; } /* This determines the OPTIONAL flag value. The field * cannot be omitted if it is the last of a SEQUENCE * and there is still data to be read. This isn't * strictly necessary but it increases efficiency in * some cases. */ if (i == (it->tcount - 1)) isopt = 0; else isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); /* attempt to read in field, allowing each to be * OPTIONAL */ ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx); if (!ret) { errtt = seqtt; goto err; } else if (ret == -1) { /* OPTIONAL component absent. * Free and zero the field. */ ASN1_template_free(pseqval, seqtt); continue; } /* Update length */ len -= p - q; } /* Check for EOC if expecting one */ if (seq_eoc && !asn1_check_eoc(&p, len)) { ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MISSING_EOC); goto err; } /* Check all data read */ if (!seq_nolen && len) { ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH); goto err; } /* If we get here we've got no more data in the SEQUENCE, * however we may not have read all fields so check all * remaining are OPTIONAL and clear any that are. */ for (; i < it->tcount; tt++, i++) { const ASN1_TEMPLATE *seqtt; seqtt = asn1_do_adb(pval, tt, 1); if (!seqtt) goto err; if (seqtt->flags & ASN1_TFLG_OPTIONAL) { ASN1_VALUE **pseqval; pseqval = asn1_get_field_ptr(pval, seqtt); ASN1_template_free(pseqval, seqtt); } else { errtt = seqtt; ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_FIELD_MISSING); goto err; } } /* Save encoding */ if (!asn1_enc_save(pval, *in, p - *in, it)) goto auxerr; *in = p; if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it)) goto auxerr; return 1; default: return 0; } auxerr: ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_AUX_ERROR); err: ASN1_item_ex_free(pval, it); if (errtt) ERR_add_error_data(4, "Field=", errtt->field_name, ", Type=", it->sname); else ERR_add_error_data(2, "Type=", it->sname); return 0; }
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc) { if (enc == -1) enc = ctx->encrypt; else { if (enc) enc = 1; ctx->encrypt = enc; } #ifdef OPENSSL_FIPS if(FIPS_selftest_failed()) { FIPSerr(FIPS_F_EVP_CIPHERINIT_EX,FIPS_R_FIPS_SELFTEST_FAILED); ctx->cipher = &bad_cipher; return 0; } #endif #ifndef OPENSSL_NO_ENGINE /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts * so this context may already have an ENGINE! Try to avoid releasing * the previous handle, re-querying for an ENGINE, and having a * reinitialisation, when it may all be unecessary. */ if (ctx->engine && ctx->cipher && (!cipher || (cipher && (cipher->nid == ctx->cipher->nid)))) goto skip_to_init; #endif if (cipher) { /* Ensure a context left lying around from last time is cleared * (the previous check attempted to avoid this if the same * ENGINE and EVP_CIPHER could be used). */ EVP_CIPHER_CTX_cleanup(ctx); /* Restore encrypt field: it is zeroed by cleanup */ ctx->encrypt = enc; #ifndef OPENSSL_NO_ENGINE if (!do_evp_enc_engine(ctx, &cipher, impl)) return 0; #endif ctx->cipher=cipher; if (ctx->cipher->ctx_size) { ctx->cipher_data=OPENSSL_malloc(ctx->cipher->ctx_size); if (!ctx->cipher_data) { EVPerr(EVP_F_EVP_CIPHERINIT_EX, ERR_R_MALLOC_FAILURE); return 0; } } else { ctx->cipher_data = NULL; } ctx->key_len = cipher->key_len; ctx->flags = 0; if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT) { if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) { EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); return 0; } } } else if(!ctx->cipher) { EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET); return 0; } #ifndef OPENSSL_NO_ENGINE skip_to_init: #endif /* we assume block size is a power of 2 in *cryptUpdate */ OPENSSL_assert(ctx->cipher->block_size == 1 || ctx->cipher->block_size == 8 || ctx->cipher->block_size == 16); if(!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) { switch(EVP_CIPHER_CTX_mode(ctx)) { case EVP_CIPH_STREAM_CIPHER: case EVP_CIPH_ECB_MODE: break; case EVP_CIPH_CFB_MODE: case EVP_CIPH_OFB_MODE: ctx->num = 0; case EVP_CIPH_CBC_MODE: OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <= (int)sizeof(ctx->iv)); if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); break; default: return 0; break; } } #ifdef OPENSSL_FIPS /* After 'key' is set no further parameters changes are permissible. * So only check for non FIPS enabling at this point. */ if (key && FIPS_mode()) { if (!(ctx->cipher->flags & EVP_CIPH_FLAG_FIPS) & !(ctx->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW)) { EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_DISABLED_FOR_FIPS); #if 0 ERR_add_error_data(2, "cipher=", EVP_CIPHER_name(ctx->cipher)); #endif ctx->cipher = &bad_cipher; return 0; } } #endif if(key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) { if(!ctx->cipher->init(ctx,key,iv,enc)) return 0; } ctx->buf_len=0; ctx->final_used=0; ctx->block_mask=ctx->cipher->block_size-1; return 1; }
static int cswift_dsa_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa) { SW_CONTEXT_HANDLE hac; SW_PARAM sw_param; SW_STATUS sw_status; SW_LARGENUMBER arg[2], res; unsigned long sig_result; BN_CTX *ctx; BIGNUM *dsa_p = NULL; BIGNUM *dsa_q = NULL; BIGNUM *dsa_g = NULL; BIGNUM *dsa_key = NULL; BIGNUM *argument = NULL; int to_return = -1; int acquired = 0; if((ctx = BN_CTX_new()) == NULL) goto err; if(!get_context(&hac)) { CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_UNIT_FAILURE); goto err; } acquired = 1; /* Prepare the params */ BN_CTX_start(ctx); dsa_p = BN_CTX_get(ctx); dsa_q = BN_CTX_get(ctx); dsa_g = BN_CTX_get(ctx); dsa_key = BN_CTX_get(ctx); argument = BN_CTX_get(ctx); if(!argument) { CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_BN_CTX_FULL); goto err; } if(!bn_wexpand(dsa_p, dsa->p->top) || !bn_wexpand(dsa_q, dsa->q->top) || !bn_wexpand(dsa_g, dsa->g->top) || !bn_wexpand(dsa_key, dsa->pub_key->top) || !bn_wexpand(argument, 40)) { CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_BN_EXPAND_FAIL); goto err; } sw_param.type = SW_ALG_DSA; sw_param.up.dsa.p.nbytes = BN_bn2bin(dsa->p, (unsigned char *)dsa_p->d); sw_param.up.dsa.p.value = (unsigned char *)dsa_p->d; sw_param.up.dsa.q.nbytes = BN_bn2bin(dsa->q, (unsigned char *)dsa_q->d); sw_param.up.dsa.q.value = (unsigned char *)dsa_q->d; sw_param.up.dsa.g.nbytes = BN_bn2bin(dsa->g, (unsigned char *)dsa_g->d); sw_param.up.dsa.g.value = (unsigned char *)dsa_g->d; sw_param.up.dsa.key.nbytes = BN_bn2bin(dsa->pub_key, (unsigned char *)dsa_key->d); sw_param.up.dsa.key.value = (unsigned char *)dsa_key->d; /* Attach the key params */ sw_status = p_CSwift_AttachKeyParam(hac, &sw_param); switch(sw_status) { case SW_OK: break; case SW_ERR_INPUT_SIZE: CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_BAD_KEY_SIZE); goto err; default: { char tmpbuf[DECIMAL_SIZE(sw_status)+1]; CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_REQUEST_FAILED); sprintf(tmpbuf, "%ld", sw_status); ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf); } goto err; } /* Prepare the argument and response */ arg[0].nbytes = dgst_len; arg[0].value = (unsigned char *)dgst; arg[1].nbytes = 40; arg[1].value = (unsigned char *)argument->d; memset(arg[1].value, 0, 40); BN_bn2bin(sig->r, arg[1].value + 20 - BN_num_bytes(sig->r)); BN_bn2bin(sig->s, arg[1].value + 40 - BN_num_bytes(sig->s)); res.nbytes = 4; /* unsigned long */ res.value = (unsigned char *)(&sig_result); /* Perform the operation */ sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_DSS_VERIFY, arg, 2, &res, 1); if(sw_status != SW_OK) { char tmpbuf[DECIMAL_SIZE(sw_status)+1]; CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_REQUEST_FAILED); sprintf(tmpbuf, "%ld", sw_status); ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf); goto err; } /* Convert the response */ to_return = ((sig_result == 0) ? 0 : 1); err: if(acquired) release_context(hac); if(ctx) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return to_return; }