/** @ingroup n8_packet * @brief Precomputes values for MD5 hashes. * * @param cipherInfo_p RW: Cipher information * @param packetObject_p RO: Pointer to packet object. May be NULL. * @param req_pp RW: Pointer to request pointer. * * @par Externals * None * * @return * Status code * * @par Errors * None * @par Assumptions * None *****************************************************************************/ static N8_Status_t n8_initializeSSL_req(N8_CipherInfo_t *cipherInfo_p, N8_Packet_t *packetObject_p, N8_Buffer_t **ctx_pp, uint32_t *ctxa_p, API_Request_t **req_pp) { N8_Status_t ret = N8_STATUS_OK; API_Request_t *req_p = NULL; do { CHECK_OBJECT(cipherInfo_p, ret); CHECK_OBJECT(packetObject_p, ret); /* initialize set the return request pointer to NULL. it wil be reset * with an actual value later if necessary. */ *req_pp = NULL; ret = n8_precompute_ssl_ipad_opad(packetObject_p->cipherInfo.macSecret, packetObject_p->cipherInfo.precompute1, packetObject_p->cipherInfo.precompute2); CHECK_RETURN(ret); } while (FALSE); /* * Clean up if we arrived from an error condition. */ if (ret != N8_STATUS_OK) { freeRequest(req_p); } return ret; } /* n8_initializeSSL_req */
// Called by libuv when the stat call for size completes. static void fileSizeCallback(uv_fs_t* request) { if (handleRequestError(request)) return; double size = (double)request->statbuf.st_size; schedulerResume(freeRequest(request), true); wrenSetSlotDouble(getVM(), 2, size); schedulerFinishResume(); }
static void fileOpenCallback(uv_fs_t* request) { if (handleRequestError(request)) return; double fd = (double)request->result; schedulerResume(freeRequest(request), true); wrenSetSlotDouble(getVM(), 2, fd); schedulerFinishResume(); }
/** @ingroup n8_event * @brief Run through the list of events and complete them. * * Run through the SDK's internal list of events, checking each one for its * completion status. If the event is completed, the user's callback is * invoked and the event freed. * * @par Externals * n8_callback_gp - Pointer to the callback threads data structure. * * @return * N8_STATUS_OK - all's well.<br> * * @par Errors * <description of possible errors><br> * * @par Assumptions * This is the only function that should increment eventReadIndex, * the read index in the SDK's list of Events. * This function should not be called if the callback thread is running. *****************************************************************************/ int N8_EventPoll(void) { int nextRead; N8_Event_t *events_p; int eventsComplete = 0; QMgrRequest_t *qreq_p = NULL; N8_Status_t usrStatus; while (n8_callbackData_gp->eventReadIndex != n8_callbackData_gp->eventWriteIndex) { events_p = &n8_callbackData_gp->n8_Events[n8_callbackData_gp->eventReadIndex]; qreq_p = (QMgrRequest_t *) events_p->state; if ( qreq_p->requestStatus == N8_QUEUE_REQUEST_FINISHED ) { if ( qreq_p->requestError != N8_QUEUE_REQUEST_ERROR ) { /* Do the callback if needed. */ if ( qreq_p->callback != NULL ) { qreq_p->callback( qreq_p ); } /* events_p->status = N8_QUEUE_REQUEST_FINISHED; */ usrStatus = N8_STATUS_OK; } else { /* events_p->status = N8_QUEUE_REQUEST_COMMAND_ERROR; */ usrStatus = N8_HARDWARE_ERROR; } /* free the request. */ freeRequest((API_Request_t *)qreq_p); /* Perform the user's callback. */ if (events_p->usrCallback) { events_p->usrCallback( events_p->usrData, usrStatus ); } /* Free the position in the Event queue */ nextRead = n8_callbackData_gp->eventReadIndex + 1; if (nextRead == n8_callbackData_gp->eventMax) { nextRead = 0; } n8_callbackData_gp->eventReadIndex = nextRead; eventsComplete++; } } return eventsComplete; }
N8_Status_t n8_handleEvent(N8_Event_t *e_p, void *hReq_p, N8_Unit_t unit, N8_QueueStatusCodes_t requestStatus) { N8_Status_t ret = N8_STATUS_OK; QMgrRequest_t *req_p; req_p = (QMgrRequest_t *)hReq_p; if (e_p != NULL) { /* This is an asynchronous request */ e_p->state = (void *) req_p; e_p->status = requestStatus; e_p->unit = unit; #ifdef SUPPORT_CALLBACK_THREAD if ((e_p->usrCallback != NULL) || (e_p->usrData != NULL)) { ret = queueEvent(e_p); } #endif } else { /* This is an synchronous request. Therefore we don't need an */ /* event, we know that the request has completed. */ #ifdef SUPPORT_DEVICE_POLL N8_QMgrDequeue(); #endif if ( req_p->requestError != N8_QUEUE_REQUEST_ERROR ) { /* Do the callback if needed. */ if ( req_p->callback != NULL ) { req_p->callback( req_p ); } /* Free the request if the event has completed successfully. */ /* If not the error handling should free the request. */ if (((API_Request_t *)req_p)->userRequest != N8_TRUE) { /* Don't delete "user allocated/ pooled" requests */ freeRequest( (API_Request_t *)req_p ); } } else { ret = N8_HARDWARE_ERROR; } } return ret; } /* n8_handleEvent */
// Called by libuv when the stat call completes. static void statPathCallback(uv_fs_t* request) { if (handleRequestError(request)) return; WrenVM* vm = getVM(); wrenEnsureSlots(vm, 4); wrenSetSlotNewList(vm, 2); wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_dev); wrenInsertInList(vm, 2, -1, 3); wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_ino); wrenInsertInList(vm, 2, -1, 3); wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_mode); wrenInsertInList(vm, 2, -1, 3); wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_nlink); wrenInsertInList(vm, 2, -1, 3); wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_uid); wrenInsertInList(vm, 2, -1, 3); wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_gid); wrenInsertInList(vm, 2, -1, 3); wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_rdev); wrenInsertInList(vm, 2, -1, 3); wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_size); wrenInsertInList(vm, 2, -1, 3); wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_blksize); wrenInsertInList(vm, 2, -1, 3); wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_blocks); wrenInsertInList(vm, 2, -1, 3); // TODO: Include access, modification, and change times once we figure out // how we want to represent it. // time_t st_atime; /* time of last access */ // time_t st_mtime; /* time of last modification */ // time_t st_ctime; /* time of last status change */ schedulerResume(freeRequest(request), true); schedulerFinishResume(); }
static void fileReadBytesCallback(uv_fs_t* request) { if (handleRequestError(request)) return; FileRequestData* data = (FileRequestData*)request->data; uv_buf_t buffer = data->buffer; size_t count = request->result; // TODO: Having to copy the bytes here is a drag. It would be good if Wren's // embedding API supported a way to *give* it bytes that were previously // allocated using Wren's own allocator. schedulerResume(freeRequest(request), true); wrenSetSlotBytes(getVM(), 2, buffer.base, count); schedulerFinishResume(); // TODO: Likewise, freeing this after we resume is lame. free(buffer.base); }
static void directoryListCallback(uv_fs_t* request) { if (handleRequestError(request)) return; uv_dirent_t entry; WrenVM* vm = getVM(); wrenEnsureSlots(vm, 3); wrenSetSlotNewList(vm, 2); while (uv_fs_scandir_next(request, &entry) != UV_EOF) { wrenSetSlotString(vm, 1, entry.name); wrenInsertInList(vm, 2, -1, 1); } schedulerResume(freeRequest(request), true); schedulerFinishResume(); }
void MemoryPort::handleResponses() { // handle responses: // - read in entries from memSysResponseFIFO if: // * memSysResponseFIFO not empty // * output FIFO not full // - check if entry corresponds to existing filled MSHR // - log statistics // - free up MSHR and put response data onto output FIFO // move responses to output FIFO int maxRespFromMemSysPerCycle = m_maxRespFromMemSysPerCycle; while(m_memSysResponseFIFO->num_available() > 0 && peOutput.num_free() > 0) { MemoryOperation * op = m_memSysResponseFIFO->read(); m_responses++; // TODO return actual data instead of the address peOutput.write(op->address); // TODO log statistics // free memory and MSHR entry int ind = findMSHRForResponse(op->address); m_mshrEntries[ind].valid = false; m_mshrEntries[ind].memRequestIssued = false; m_availableMSHRCount++; freeRequest(op); // limit response rate if(--maxRespFromMemSysPerCycle == 0) break; } }
/** @ingroup dh * @brief Computes a Diffie-Hellman exponentiation as required to compute * Diffie-Hellman public values from a secret value and a Diffie-Hellman * key (or group). * * Description: * The key or group is specified by DHKeyObject which must have been * previously initialized with the appropriate group generator g, modulus p, * and modulus size by a call to N8_DHInitializeKey. The DH secret value * used as the exponent is specified in XValue, and must be of the same * size as the modulus size in DHKeyObject. GValue specifies the value * to be exponentiated and must also be the same size as the modulus. * GValue may be null, in which case the generator g from DHKeyObject is * used as the GValue. The result of the calculation is returned in * GXValue and is the same size as the modulus. The value computed is * GXValue = ( GValue ** XValue ) mod p. Thus this routine computes a * modular exponentiation. * This call can be used to compute from a private x value the value * X = g**x mod p that is the public X value sent to the other respondent * in a Diffie-Hellman exchange. (In this case the GValue is set to null, * and x is used for XValue.) When the respondent's corresponding Y value * (Y = g**y mod p, y = the respondent's private y) is received, this call * can then be used to compute the common shared secret XY = g**(xy) = YX by * using X for the GValue and the received Y as the XValue. * * Parameters: * @param key_p RO: The caller supplied DHKeyObject containing * the appropriate Diffie-Hellman values * and pre-computed DH constants. * @param gValue RO: The value to be raised to a power. * If null, then the generator g value from * DHKeyObject is used. GValue must be the * same size as the modulus p from DHKeyObject. * @param xValue RO: The exponent. Must be supplied. XValue * must be the same size as the * modulus p from DHKeyObject * @param gxValue WO: GValue raised to the XValue power, mod p. * GXValue will be the same * size as the modulus p from DHKeyObject. * @param event_p RW: On input, if null the call is synchronous * and no event is returned. The operation * is complete when the call returns. If * non-null, then the call is asynchronous; * an event is returned that can be used to * determine when the operation completes. * * @return * ret - returns N8_STATUS_OK if successful or Error value. * * @par Errors: * N8_INVALID_OBJECT - context request object is NULL<BR> * N8_INVALID_KEY - The DHKeyObject is not a valid key * object * for this operation. * * @par Assumptions: **********************************************************************/ N8_Status_t N8_DHCompute(N8_DH_KeyObject_t *key_p, N8_Buffer_t *gValue_p, N8_Buffer_t *xValue_p, N8_Buffer_t *gxValue_p, N8_Event_t *event_p) { N8_Status_t ret = N8_STATUS_OK; API_Request_t *req_p = NULL; unsigned int nBytes; N8_Buffer_t *g_p; N8_Buffer_t *x_p; N8_Buffer_t *res_p; uint32_t g_a; uint32_t x_a; uint32_t res_a; unsigned int g_len; unsigned int x_len; unsigned int res_len; N8_Boolean_t useShortCommandBlock = N8_FALSE; do { ret = N8_preamble(); CHECK_RETURN(ret); CHECK_OBJECT(key_p, ret); CHECK_OBJECT(xValue_p, ret); CHECK_OBJECT(gxValue_p, ret); CHECK_STRUCTURE(key_p->structureID, N8_DH_STRUCT_ID, ret); /* compute the lengths of all of the parameters as a convenience */ g_len = key_p->modulusLength; x_len = key_p->modulusLength; res_len = key_p->modulusLength; nBytes = (NEXT_WORD_SIZE(x_len) + NEXT_WORD_SIZE(res_len)); /* gValue_p is allowed to be NULL. if so, use the g from the key object. */ if (gValue_p == NULL) { useShortCommandBlock = N8_TRUE; /* allocate user-space buffer */ ret = createPKRequestBuffer(&req_p, key_p->unitID, N8_CB_COMPUTE_G_XMODP_NUMCMDS_SHORT, resultHandlerGeneric, nBytes); } else { nBytes += NEXT_WORD_SIZE(g_len); /* allocate user-space buffer */ ret = createPKRequestBuffer(&req_p, key_p->unitID, N8_CB_COMPUTE_G_XMODP_NUMCMDS_LONG, resultHandlerGeneric, nBytes); } CHECK_RETURN(ret); /* set up the addressing for the pointers */ x_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset); x_a = req_p->qr.physicalAddress + req_p->dataoffset; res_p = x_p + NEXT_WORD_SIZE(x_len); res_a = x_a + NEXT_WORD_SIZE(x_len); memcpy(x_p, xValue_p, x_len); req_p->copyBackSize = x_len; req_p->copyBackFrom_p = res_p; req_p->copyBackTo_p = gxValue_p; if (useShortCommandBlock == N8_TRUE) { ret = cb_computeGXmodp_short(req_p, x_a, key_p->p_a, key_p->cp_a, key_p->gRmodP_a, res_a, key_p->modulusLength, req_p->PK_CommandBlock_ptr); } else { /* gValue_p is not NULL, copy the user-space */ /* data into our kernel space buffers */ g_p = res_p + NEXT_WORD_SIZE(res_len); g_a = res_a + NEXT_WORD_SIZE(res_len); memcpy(g_p, gValue_p, g_len); ret = cb_computeGXmodp_long(req_p, g_a, x_a, key_p->p_a, key_p->cp_a, key_p->RmodP_a, res_a, key_p->modulusLength, req_p->PK_CommandBlock_ptr); } CHECK_RETURN(ret); QUEUE_AND_CHECK(event_p, req_p, ret); HANDLE_EVENT(event_p, req_p, ret); } while (FALSE); DBG(("DH computed\n")); /* * Deallocate the request if we arrived from an error condition. */ if (ret != N8_STATUS_OK) { freeRequest(req_p); } return ret; } /* N8_DHCompute */
/** @ingroup dh * @brief Initializes the specified DHKeyObject so that it can be used * in Diffie-Hellman operations. The KeyMaterial object (structure) * contains the appropriate group generator g, modulus p, and modulus size. * * Description: * This call pre-computes various constant values from the supplied * parameters and initializes DHKeyObject with these values. By * pre-computing these values, Diffie-Hellman computations can be done * faster than if these constants must be computed on each operation. * Once a DHKeyObject has been initialized, it can be used repeatedly * in multiple DH operations. It does not ever need to be re-initialized, * unless the actual key value(s) change (i.e., unless the key itself * changes). * * @param key_p RW: The caller allocated DHKeyObject, initialized * by this call with the appropriate DH key * material and pre-computed DH constants * depending on the value of the KeyType parameter * @param material_p RO: Pointer to the key material to use in initializing * DHKeyObject. * * @return * ret - returns N8_STATUS_OK if successful or Error value. * * @par Errors: * N8_INVALID_OBJECT - DH key or key material object is NULL<BR> * * @par Assumptions: * None. **********************************************************************/ N8_Status_t N8_DHInitializeKey(N8_DH_KeyObject_t *key_p, N8_DH_KeyMaterial_t *material_p, N8_Event_t *event_p) { N8_Status_t ret = N8_STATUS_OK; int nBytes; API_Request_t *req_p = NULL; do { ret = N8_preamble(); CHECK_RETURN(ret); CHECK_OBJECT(key_p, ret); CHECK_OBJECT(material_p, ret); key_p->unitID = material_p->unitID; /* check the modulus size to ensure it is 1 <= ms <= 512. return * N8_INVALID_SIZE if not. */ if (material_p->modulusSize < N8_DH_MIN_MODULUS_SIZE || material_p->modulusSize > N8_DH_MAX_MODULUS_SIZE) { ret = N8_INVALID_KEY_SIZE; break; } /* Allocate space for the initialized key. we must compute 'R mod p' and 'cp' * for use in subsequent DHComputes. */ key_p->modulusLength = material_p->modulusSize; nBytes = (NEXT_WORD_SIZE(key_p->modulusLength) + /* g */ NEXT_WORD_SIZE(key_p->modulusLength) + /* p */ NEXT_WORD_SIZE(key_p->modulusLength) + /* R mod p */ NEXT_WORD_SIZE(key_p->modulusLength) + /* g R mod p */ NEXT_WORD_SIZE(PK_DH_CP_Byte_Length));/* cp */ /* Allocate a kernel buffer to hold data accessed by the NSP2000 */ key_p->kmem_p = N8_KMALLOC_PK(nBytes); CHECK_OBJECT(key_p->kmem_p, ret); memset(key_p->kmem_p->VirtualAddress, 0, nBytes); /* Compute virtual addresses within the kernel buffer */ key_p->g = (N8_Buffer_t *) key_p->kmem_p->VirtualAddress; key_p->p = key_p->g + NEXT_WORD_SIZE(key_p->modulusLength); key_p->R_mod_p = key_p->p + NEXT_WORD_SIZE(key_p->modulusLength); key_p->gR_mod_p = key_p->R_mod_p + NEXT_WORD_SIZE(key_p->modulusLength); key_p->cp = key_p->gR_mod_p + NEXT_WORD_SIZE(key_p->modulusLength); /* Compute physical addresses within the kernel buffer */ key_p->g_a = key_p->kmem_p->PhysicalAddress; key_p->p_a = key_p->g_a + NEXT_WORD_SIZE(key_p->modulusLength); key_p->RmodP_a = key_p->p_a + NEXT_WORD_SIZE(key_p->modulusLength); key_p->gRmodP_a = key_p->RmodP_a + NEXT_WORD_SIZE(key_p->modulusLength); key_p->cp_a = key_p->gRmodP_a + NEXT_WORD_SIZE(key_p->modulusLength); /* Set up the memory for p and g and copy from the key material */ memcpy(key_p->p, material_p->p, material_p->modulusSize); memcpy(key_p->g, material_p->g, material_p->modulusSize); /* Set the structure ID */ key_p->structureID = N8_DH_STRUCT_ID; /* allocate user-space command buffer */ ret = createPKRequestBuffer(&req_p, key_p->unitID, N8_CB_PRECOMPUTE_DHVALUES_NUMCMDS, NULL, 0); CHECK_RETURN(ret); ret = cb_precomputeDHValues(req_p, key_p->g_a, key_p->p_a, key_p->RmodP_a, key_p->gRmodP_a, key_p->cp_a, key_p->modulusLength, req_p->PK_CommandBlock_ptr, key_p->unitID); CHECK_RETURN(ret); QUEUE_AND_CHECK(event_p, req_p, ret); HANDLE_EVENT(event_p, req_p, ret); } while(FALSE); /* * Deallocate the request if we arrived from an error condition. */ if (ret != N8_STATUS_OK) { /* free the request */ freeRequest(req_p); /* free the key also, if it has been allocated */ if (key_p != NULL) { /* ignore the return code as we want to return the original anyway */ (void) N8_DHFreeKey(key_p); } } return ret; } /* N8_DHInitializeKey */
void *thread_func(void *new_socket_ref) { int new_socket = *(int*)new_socket_ref; //int* index = (int *) param; do{ //printf("--------------\nHebra %i\n",*index); result = recv(new_socket,buffer,80,0); if(result==-1){ perror("Servidor:Recv"); exit(1); } /* if(strcmp(buffer,"EOT")==0){ printf("Se ha recibido EOT\n"); EOT=1; }else if(strcmp(buffer,"EOT")!=0){ printf("El mensaje recibido fue:\n%s\n",buffer);*/ printf("%s\n",buffer); split_request(buffer,&req); switch(req.req_type){ case GET_STATE: printf("GET_STATE %s\n",req.req[0]); //printf("Buscamos usuario...\n"); user_ptr = getUser(req.req[0],user_list); if(user_ptr!=NULL){ sprintf(buffer,"%i %s %i", STATE,user_ptr->name,user_ptr->state); //printf("Encontrado\n Respuesta a enviar: %s\n",buffer); }else{ printf("El usuario no existe\n"); sprintf(buffer,"%i",ERROR); } if(send(new_socket,buffer,80,0)==-1){ printf("Servidor:Send\n"); exit(1); } break; case POST_NAME_LOCATION_STATE: printf("POST_NAME_LOCATION_STATE %s %s %i\n", req.req[0],req.req[1],atoi(req.req[2])); strcpy(user.name,req.req[0]); strcpy(user.location,req.req[1]); user.state = atoi(req.req[2]); user_list = addUser(&user,user_list); showUsers(user_list); sprintf(buffer,"%i",OK); if(send(new_socket,buffer,80,0)==-1){ printf("Servidor:Send\n"); exit(1); } break; case AUTH: printf("AUTH %s\n",req.req[0]); //Comprobamos si existe el usuario user_ptr = getUser(req.req[0],user_list); if(user_ptr!=NULL){//Si Existe mandamos reto challenge = random(); sprintf(buffer,"%i %i",CHALLENGE,challenge); printf("Enviado reto: %s\n",buffer); if(send(new_socket,buffer,80,0)==-1){ printf("Servidor:Send\n"); exit(1); } result = recv(new_socket,buffer,80,0); if(result==-1){ perror("Servidor:Recv"); exit(1); } split_request(buffer,&req); //printf("Recibimos %s\n",buffer); strcpy(location,req.req[1]); state = atoi(req.req[2]); //Esperamos md5 name:reto:secreto result = recv(new_socket,out,16,0); for (i=0; i<16; i++) { printf("%02x", out[i]); } printf("\n"); //Comparamos md5 recibido con nuestro md5 sprintf(buffer,"%s%i%s",user_ptr->name,challenge,user_ptr->secret); printf("OUR MD5 %s : ",buffer); getMD5(buffer,strlen(buffer),md5); for (i=0; i<16; i++) { printf("%02x", md5[i]); } printf("\n"); if(memcmp(md5,out,16)==0){ printf("MATCH MD5\n"); strcpy(user_ptr->location,location); user_ptr->state = state; sprintf(buffer,"%i",OK); if(send(new_socket,buffer,80,0)==-1){ printf("Servidor:Send\n"); exit(1); } }else{ printf("MD5 incorrecto.\n"); sprintf(buffer,"%i",ERROR); if(send(new_socket,buffer,80,0)==-1){ printf("Servidor:Send\n"); exit(1); } } }else{//Si no existe mandamos error printf("No existe el usuario.\n"); sprintf(buffer,"%i",ERROR); if(send(new_socket,buffer,80,0)==-1){ printf("Servidor:Send\n"); exit(1); } } break; case GET_LOCATION: printf("GET_LOCATION %s\n",req.req[0]); user_ptr = getUser(req.req[0],user_list); if(user_ptr!=NULL){ sprintf(buffer,"%i %s %s", LOCATION,user_ptr->name,user_ptr->location); }else{ sprintf(buffer,"%i",ERROR); } if(send(new_socket,buffer,80,0)==-1){ printf("Servidor:Send\n"); exit(1); } break; case EXIT: printf("EXIT\n"); printf("Fin de la conexion\n"); EOT=1; } freeRequest(&req); //} //printf("-----\n"); }while(!EOT); // the function must return something - NULL will do return NULL; }
/** @ingroup n8_event * @brief Runs as a seperate thread polling the list of events and completing * them. * * This function is started as a seperate thread. It continually runs through * the SDK's internal list of events, checking each one for its * completion status. If the event is completed, the user's callback is * invoked and the event freed. * * @par Externals * * @return * N8_STATUS_OK - all's well.<br> * * @par Errors * <description of possible errors><br> * * @par Assumptions * This is the only function that should increment eventReadIndex, * the read index in the SDK's list of Events. * N8_EventPoll should not be called if this thread is running. *****************************************************************************/ N8_Status_t n8_callbackThread(N8_CallbackData_t *callbackData_p) { int nextRead; N8_Event_t *events_p; QMgrRequest_t *qreq_p = NULL; N8_Status_t usrStatus; /* Perform Linux Kernal specific initialization */ #ifdef __KERNEL__ threadStruct = current; /* Mask out the unwanted signals */ current->blocked.sig[0] |= sigmask(SIGINT) | sigmask(SIGTERM); recalc_sigpending(current); /* set name of this process (max 15 chars + 0 !) */ strcpy(current->comm, "NSP2000 Thread"); #endif while (callbackData_p->n8_thread == TRUE) { if (callbackData_p->eventReadIndex != callbackData_p->eventWriteIndex) { events_p = &callbackData_p->n8_Events[callbackData_p->eventReadIndex]; qreq_p = (QMgrRequest_t *) events_p->state; if ( qreq_p->requestStatus == N8_QUEUE_REQUEST_FINISHED ) { if ( qreq_p->requestError != N8_QUEUE_REQUEST_ERROR ) { /* Do the callback if needed. */ if ( qreq_p->callback != NULL ) { qreq_p->callback( qreq_p ); } /* events_p->status = N8_QUEUE_REQUEST_FINISHED; */ usrStatus = N8_STATUS_OK; } else { /* events_p->status = N8_QUEUE_REQUEST_COMMAND_ERROR; */ usrStatus = N8_HARDWARE_ERROR; } /* free the request. */ freeRequest((API_Request_t *)qreq_p); /* Perform the user's callback. */ if (events_p->usrCallback) { events_p->usrCallback( events_p->usrData, usrStatus ); } /* Free the position in the Event queue */ nextRead = callbackData_p->eventReadIndex + 1; if (nextRead == callbackData_p->eventMax) { nextRead = 0; } callbackData_p->eventReadIndex = nextRead; } else { N8_WaitOnRequest(callbackData_p->timeout); } } else { N8_WaitOnRequest(callbackData_p->timeout); } } /* Free the resources allocated by callback initialization. */ /* This is done here instead of in callbackShutdown to avoid freeing */ /* resources while the callback thread continues to reference them. */ callbackData_p->eventMax = 0; N8_deleteProcessSem(&callbackData_p->eventLock); N8_UFREE(callbackData_p); return N8_STATUS_OK; }
static void fileCloseCallback(uv_fs_t* request) { if (handleRequestError(request)) return; schedulerResume(freeRequest(request), false); }
/** @ingroup ipsec_packet * @brief Encrypt and authenticate an entire IPSec record. * * Encrypt and authenticate an entire IPSec record. PacketObject is a packet * object previously initialized by a call to N8_PacketInitialize specifying * IPSec as the packet protocol to use. PacketObject provides encryption and * authentication information to be used in the call. The decryption algorithm * can only be DES as specified when PacketObject was initialized. The * authentication algorithm can be HMAC-MD5-96 or HMACSHA-1-96 as specified * when PacketObject was initialized. Thus, two combinations of * encryption/authentication can be performed: DES/HMAC-MD5-96 and * DES/HMAC-SHA-1-96. The SPI parameter specifies the IPSec Security Parameter * Index of the message. The SPI is used along with the sequence number and * the DES initialization vector (taken from information specified in the * PacketObject) in the authentication computation. The message contents of the * IPSec packet is given in Data; its length in bytes must be specified in * packetLength. Note that Data must include all of the information to be * encrypted according to the IPSec specification; this includes the TCP and * IP headers if present (the IP header is only present in tunnel mode) and must * also include the terminating pad, pad length and next header fields. * The byte length of Data is specified in packetLength and must also include all * of these fields. packetLength must be a multiple of 8. The fully encrypted and * authenticated Data is returned in Result, including the encrypted data * followed by the HMAC-MD5-96 or HMAC-SHA-1-96 authentication value. * * @param packetObject_p RW: The object denoting the decryption and * verification computation to be done. PacketObject * must have been initialized for use with IPSec. * The state in PacketObject will be updated if * necessary as part of the call. <BR> * @param packet_p RO: The ESP packet beginning with the Security * Parameter Index, Sequence Number and data payload * including DES initialization vector and ending * with the pad, pad length, and next header fields * as specified by the IPSec protocol.<BR> * @param packetLength RO: The length of Data, in bytes, from 8 bytes - 17 KBytes * inclusive. A length < 8 or not a multiple of 8 is * illegal and results in an error.<BR> * @param result_p WO: The encrypted / authenticated data, complete with * authentication data. Result must be of sufficient * size to hold the fully encrypted & authenticated * message; its size must be at least packetLength + * IPSEC_AUTHENTICATION_DATA_LENGTH * (hash size for all hash algorithms).<BR> * @param event_p RW: On input, if null the call is synchronous and no * event is returned. The operation is complete when * the call returns. If non-null, then the call is * asynchronous; an event is returned that can be used * to determine when the operation completes. * * * @return * packetObject_p - The state in PacketObject will be updated if necessary as * part of the call. * result_p - The encrypted / authenticated data, complete with * authentication data. * ret - returns N8_STATUS_OK if successful or Error value. * * @par Errors: * N8_INVALID_OBJECT - packet object is zero, couldn't write to unspecified * address<BR> * N8_INVALID_INPUT_SIZE - The value of packetLength is less then 8 or bigger * then 17 KBytes or is not a multiple of 8. * N8_UNIMPLEMENTED_FUNCTION - not supported protocol configuration requested * N8_HARDWARE_ERROR - couldn't write to context memory * * * @par Assumptions: * packetObject_p was initialized and all parameters checked.<BR> * For IPSec, the authentication data is always * 12 (IPSEC_AUTHENTICATION_DATA_LENGTH) bytes (the 12 most * significant bytes of the standard 16 byte MD5 or 20 byte SHA-1 value) and * is not encrypted. Result is always packetLength + 12 bytes in length. * The caller is responsible for ensuring that Result is this size. *****************************************************************************/ N8_Status_t N8_IPSecEncryptAuthenticate(N8_Packet_t *packetObject_p, N8_IPSecPacket_t *packet_p, int packetLength, N8_IPSecPacket_t *result_p, N8_Event_t *event_p ) { N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */ API_Request_t *req_p = NULL; /* request buffer */ EA_CMD_BLOCK_t *next_cb_p = NULL; int dataLength; unsigned long pack_a; N8_Buffer_t *pack_p = NULL; unsigned long res_a; N8_Buffer_t *res_p = NULL; N8_Buffer_t *ctx_p = NULL; uint32_t ctx_a; int nBytes; int numCommands; int numCtxBytes = 0; void *callbackFcn = NULL; n8_ctxLoadFcn_t ctxLoadFcn; DBG(("N8_IPSecEncryptAuthenticate\n")); do { /* verify data length */ if ((packetLength < IPSEC_DATA_LENGTH_MIN) || (packetLength > IPSEC_DATA_LENGTH_MAX)) { DBG(("Data length is out of range\n")); ret = N8_INVALID_INPUT_SIZE; break; } if (packetLength % IPSEC_DATA_BLOCK_SIZE) { DBG(("Data length is not a multiple of %d\n", IPSEC_DATA_BLOCK_SIZE)); ret = N8_INVALID_INPUT_SIZE; break; } /* verify packet object */ CHECK_OBJECT(packetObject_p, ret); CHECK_STRUCTURE(packetObject_p->structureID, N8_PACKET_STRUCT_ID, ret); /* verify data object */ CHECK_OBJECT(packet_p, ret); /* verify result object */ CHECK_OBJECT(result_p, ret); dataLength = packetLength - IPSEC_PACKET_HEADER_LENGTH; numCommands = N8_CB_EA_IPSECENCRYPTAUTHENTICATE_NUMCMDS; if (packetObject_p->contextLoadNeeded == N8_TRUE) { numCommands += packetObject_p->ctxLoadCmds; numCtxBytes = NEXT_WORD_SIZE(EA_CTX_Record_Byte_Length); } /* compute the space needed for the size of context load, if required */ nBytes = NEXT_WORD_SIZE(HMAC_LENGTH) + numCtxBytes; /* If the data must be copied to a kernel before the chip can operate */ /* on it, compute the additional space required and setup the callback */ /* function to copy the result once the operation has completed. */ if (packetObject_p->mode == N8_PACKETMEMORY_NONE) { nBytes += NEXT_WORD_SIZE(dataLength) + /* packet data length pack_p */ NEXT_WORD_SIZE(packetLength);/* result packet length res_p */ callbackFcn = resultHandlerGeneric; } /* create request buffer */ ret = createEARequestBuffer(&req_p, packetObject_p->unitID, numCommands, callbackFcn, nBytes); CHECK_RETURN(ret); /* Compute the context memory pointers. */ ctx_a = req_p->qr.physicalAddress + req_p->dataoffset; ctx_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset); /* Compute the addresses for the packet and result buffer. */ if (packetObject_p->mode == N8_PACKETMEMORY_NONE) { /* The data must be copied to this kernel before the chip can operate */ /* on it, compute the addresses within the kernel buffer and copy in */ /* the packet. */ pack_a = ctx_a + numCtxBytes; pack_p = ctx_p + numCtxBytes; res_a = pack_a + NEXT_WORD_SIZE(dataLength); res_p = pack_p + NEXT_WORD_SIZE(dataLength); memcpy(pack_p, &packet_p[IPSEC_DATA_OFFSET], dataLength); } else { /* The chip can access the data directly, compute the */ /* physical addresses of the packet & result buffer. */ pack_a = N8_VirtToPhys(&packet_p[IPSEC_DATA_OFFSET]); res_a = N8_VirtToPhys(&result_p[IPSEC_DATA_OFFSET]); } next_cb_p = req_p->EA_CommandBlock_ptr; memcpy(result_p, packet_p, IPSEC_PACKET_HEADER_LENGTH); packetObject_p->cipherInfo.key.IPsecKeyDES.sequence_number = IPSEC_EXTRACT_SEQUENCE_NIMBER(packet_p); /* generate the command blocks necessary to load the context, if required */ if (packetObject_p->contextLoadNeeded == N8_TRUE) { /* Generate the command blocks for the Context Load */ ctxLoadFcn = (n8_ctxLoadFcn_t)packetObject_p->ctxLoadFcn; ret = ctxLoadFcn(req_p, next_cb_p, packetObject_p, &packetObject_p->cipherInfo, packetObject_p->packetHashAlgorithm, ctx_p, ctx_a, &next_cb_p); CHECK_RETURN(ret); packetObject_p->contextLoadNeeded = N8_FALSE; } memcpy(&packetObject_p->cipherInfo.IV[0], packet_p+IPSEC_IV_OFFSET, N8_DES_KEY_LENGTH); cb_ea_IPsec(next_cb_p, packetObject_p, pack_a, res_a, dataLength, IPSEC_EXTRACT_SPI(packet_p), packetObject_p->encOpCode); req_p->copyBackTo_p = result_p + IPSEC_DATA_OFFSET; req_p->copyBackFrom_p = res_p; req_p->copyBackSize = dataLength + HMAC_LENGTH; QUEUE_AND_CHECK(event_p, req_p, ret) HANDLE_EVENT(event_p, req_p, ret); } while (FALSE); if (ret != N8_STATUS_OK) { freeRequest(req_p); } DBG(("N8_IPSecEncryptAuthenticate - FINISHED\n")); return ret; } /* N8_IPSecEncryptAuthenticate */
/** @ingroup ipsec_packet * @brief Decrypt and verify an entire IPSec record. * * Decrypt and verify an entire IPSec record. PacketObject is a packet object * previously initialized by a call to N8_PacketInitialize specifying IPSec * as the packet protocol to use. PacketObject provides encryption and * authentication information to be used in the call. The decryption algorithm * can only be DES as specified when PacketObject was initialized. The * authentication algorithm can be HMAC-MD5-96 or HMAC-SHA-1-96 as specified * when PacketObject was initialized. Thus, two combinations of * decryption/verification can be performed: DES/HMAC-MD5-96 and DES/HMAC-SHA-1-96. * The SPI parameter specifies the IPSec Security Parameter Index of the message. * The SPI is used along with the sequence number and the DES initialization * vector (taken from PacketObject) in the authentication computation. The * message contents of the encrypted and authenticated IPSec packet is given * in EncryptedData; its length in bytes must be specified in encryptedPacketLength. * Note that EncryptedData must end with the unencrypted12-byte authentication * value as required by the IPSec specification. The byte length of EncryptedData * including the 12 byte authentication value is specified in encryptedPacketLength. * encryptedPacketLength must be at least 20 (i.e., EncryptedData must consist of * at least one DES block to be decrypted plus the mandatory 12 byte * authentication value), and must be of the form 12 + n*8 for n > 0. The decrypted * EncryptedData is returned in Result, including the decrypted data followed by * the 12 bytes of authentication data. Result is always encryptedPacketLength * bytes in length. The caller is responsible for ensuring that Result is at * least this size. This call also calculates the authentication value on the * EncryptedData and compares this calculated value to the value at the end of * EncryptedData. If these two values are equal, the verification succeeds and * True is returned in Verify, otherwise False is returned in Verify. * * * @param packetObject_p RW: The object denoting the decryption and * verification computation to be done. PacketObject * must have been initialized for use with IPSec. * The state in PacketObject will be updated if * necessary as part of the call. <BR> * @param encryptedPacket_p RO: The message portion / contents of the IPSec packet.<BR> * @param encryptedPacketLength RO: The length of EncryptedData, in bytes, * from 20 bytes - 18 KBytes inclusive. A length * less than 20 or not of the form 12+n*8 is illegal * and results in an error.<BR> * @param Verify WO: Returned as True if the computed authentication * value on EncryptedData matches the authentication * value contained at the end of EncryptedData; * otherwise False is returned. If Verify is False, * the contents of Result may be gibberish and/or * have been altered.<BR> * @param result_p WO: The decrypted / authenticated data, complete * with authentication data. Result must be of * sufficient size to hold the decrypted & * authenticated message; its size must be at least * EncryptedDataLeng.<BR> * @param event_p RW: On input, if null the call is synchronous and no * event is returned. The operation is complete when * the call returns. If non-null, then the call is * asynchronous; an event is returned that can be used * to determine when the operation completes. * * * @return * packetObject_p - The state in PacketObject will be updated if necessary as * part of the call. * result_p - The encrypted / authenticated data, complete with * authentication data. * ret - returns N8_STATUS_OK if successful or Error value. * * @par Errors: * N8_INVALID_OBJECT - packet object is zero, couldn't write to unspecified * address<BR> * N8_INVALID_INPUT_SIZE - The value of packetLength is < 20 or > 18 KBytes or * is not of the form 12 + n*8; no operation is * performed and no result is returned. * N8_UNIMPLEMENTED_FUNCTION - not supported protocol configuration requested * N8_HARDWARE_ERROR - couldn't write to context memory * * * @par Assumptions: * packetObject_p was initialized and all parameters checked. *****************************************************************************/ N8_Status_t N8_IPSecDecryptVerify( N8_Packet_t *packetObject_p, N8_IPSecPacket_t *encryptedPacket_p, int encryptedPacketLength, N8_Buffer_t *computedHMAC_p, N8_Boolean_t *verify_p, N8_IPSecPacket_t *result_p, N8_Event_t *event_p ) { N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */ API_Request_t *req_p = NULL; /* request buffer */ EA_CMD_BLOCK_t *next_cb_p = NULL; int dataLength; unsigned long pack_a; N8_Buffer_t *pack_p = NULL; unsigned long res_a; N8_Buffer_t *res_p = NULL; N8_Buffer_t *ctx_p = NULL; uint32_t ctx_a; int nBytes; int numCommands; int numCtxBytes = 0; ipsecVerifyPostDataStruct_t *postData_p = NULL; n8_ctxLoadFcn_t ctxLoadFcn; DBG(("N8_IPSecDecryptVerify\n")); do { *verify_p = N8_FALSE; /* verify data length */ if ((encryptedPacketLength < IPSEC_DECRYPTED_DATA_LENGTH_MIN) || (encryptedPacketLength > IPSEC_DATA_LENGTH_MAX)) { DBG(("Data length is out of range\n")); ret = N8_INVALID_INPUT_SIZE; break; } if ((encryptedPacketLength - IPSEC_AUTHENTICATION_DATA_LENGTH) % IPSEC_DATA_BLOCK_SIZE) { DBG(("Data length is not a multiple of %d\n", IPSEC_DATA_BLOCK_SIZE)); ret = N8_INVALID_INPUT_SIZE; break; } /* verify packet object */ CHECK_OBJECT(packetObject_p, ret); CHECK_STRUCTURE(packetObject_p->structureID, N8_PACKET_STRUCT_ID, ret); /* verify encrypted data object */ CHECK_OBJECT(encryptedPacket_p, ret); /* verify result object */ CHECK_OBJECT(result_p, ret); #ifdef NO_MAC_COPYBACK CHECK_OBJECT(computedHMAC_p, ret); #endif dataLength = encryptedPacketLength - IPSEC_PACKET_HEADER_LENGTH; numCommands = N8_CB_EA_IPSECDECRYPTVERIFY_NUMCMDS; if (packetObject_p->contextLoadNeeded == N8_TRUE) { numCommands += packetObject_p->ctxLoadCmds; numCtxBytes = NEXT_WORD_SIZE(sizeof(EA_ARC4_CTX)); } /* compute the space needed for the chip to place the result */ nBytes = NEXT_WORD_SIZE(HMAC_LENGTH) + numCtxBytes; /* context to load */ if (packetObject_p->mode == N8_PACKETMEMORY_NONE) { nBytes += NEXT_WORD_SIZE(dataLength * 2); } /* create request buffer */ ret = createEARequestBuffer(&req_p, packetObject_p->unitID, numCommands, resultHandlerIPSecVerify, nBytes); CHECK_RETURN(ret); req_p->copyBackCommandBlock = N8_TRUE; /* Compute the addresses for the context. */ ctx_a = req_p->qr.physicalAddress + req_p->dataoffset; ctx_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset); /* Compute the addresses for the packet and result buffer. */ if (packetObject_p->mode == N8_PACKETMEMORY_NONE) { /* The data must be copied to this kernel before the chip can operate */ /* on it, compute the addresses within the kernel buffer and copy in */ /* the packet. */ pack_a = ctx_a + numCtxBytes; pack_p = ctx_p + numCtxBytes; res_a = pack_a + NEXT_WORD_SIZE(dataLength); res_p = pack_p + NEXT_WORD_SIZE(dataLength); memcpy(pack_p, encryptedPacket_p + IPSEC_DATA_OFFSET, dataLength); } else { /* The chip can access the data directly, compute the */ /* physical addresses of the packet & result buffer. */ pack_a = N8_VirtToPhys(encryptedPacket_p + IPSEC_DATA_OFFSET); res_a = N8_VirtToPhys(result_p + IPSEC_DATA_OFFSET); } next_cb_p = req_p->EA_CommandBlock_ptr; /* generate the command blocks necessary to load the context, if required */ if (packetObject_p->contextLoadNeeded == N8_TRUE) { /* Generate the command blocks for the Context Load */ ctxLoadFcn = (n8_ctxLoadFcn_t)packetObject_p->ctxLoadFcn; ret = ctxLoadFcn(req_p, next_cb_p, packetObject_p, &packetObject_p->cipherInfo, packetObject_p->packetHashAlgorithm, ctx_p, ctx_a, &next_cb_p); CHECK_RETURN(ret); packetObject_p->contextLoadNeeded = N8_FALSE; } memcpy(&packetObject_p->cipherInfo.IV[0], encryptedPacket_p+8,8); packetObject_p->cipherInfo.key.IPsecKeyDES.sequence_number = IPSEC_EXTRACT_SEQUENCE_NIMBER(encryptedPacket_p); cb_ea_IPsec(next_cb_p, packetObject_p, pack_a, res_a, dataLength, IPSEC_EXTRACT_SPI(encryptedPacket_p), packetObject_p->decOpCode); postData_p = (ipsecVerifyPostDataStruct_t *)req_p->postProcessBuffer; postData_p->computedHMAC_p = computedHMAC_p; postData_p->data_p = result_p + IPSEC_DATA_OFFSET; postData_p->res_p = res_p; postData_p->dataLength = dataLength; postData_p->verify_p = verify_p; postData_p->hashAlgorithm = packetObject_p->packetHashAlgorithm; /* setup post processing buffer pointer */ req_p->postProcessingData_p = (void *) postData_p; /* decrypt data */ QUEUE_AND_CHECK(event_p, req_p, ret) HANDLE_EVENT(event_p, req_p, ret); /* compare authentication values */ memcpy(result_p, encryptedPacket_p, IPSEC_PACKET_HEADER_LENGTH); if (*verify_p == N8_TRUE) { packetObject_p->cipherInfo.key.IPsecKeyDES.sequence_number = IPSEC_EXTRACT_SEQUENCE_NIMBER(encryptedPacket_p); memcpy(&packetObject_p->cipherInfo.IV[0], encryptedPacket_p+IPSEC_IV_OFFSET, N8_DES_KEY_LENGTH); } } while (FALSE); if (ret != N8_STATUS_OK) { freeRequest(req_p); } DBG(("N8_IPSecDecryptVerify - FINISHED\n")); return ret; } /* N8_IPSecDecryptVerify */
/** @ingroup n8_ssltls * @brief Encrypt/Authenticate an SSL or TLS message * * An entire SSL or TLS record is encrypted/authenticated. * * @param packetObj_p RW: Pointer to a packet object which was * previously initialized for SSL or TLS * @param packet_p RO: Pointer to packet * @param result_p RW: Pointer to pre-allocated buffer where the * results will be stored. * @param request RW: Kernel request buffer used when mode = * N8_PACKETMEMORY_REQUEST. * @param event_p RW: Asynchronous event pointer. * * @par Externals * None * * @return * Error condition if raised. * * @par Errors * None * * @par Assumptions * None *****************************************************************************/ N8_Status_t N8_SSLTLSEncryptAuthenticateMemory(N8_Packet_t *packetObj_p, const N8_SSLTLSPacket_t *packet_p, N8_SSLTLSPacket_t *result_p, N8_RequestHandle_t request, N8_Event_t *event_p) { N8_Status_t ret = N8_STATUS_OK; API_Request_t *req_p = NULL; EA_CMD_BLOCK_t *next_cb_p = NULL; uint16_t length; short int encLen; short int packetLen; N8_Buffer_t *res_p = NULL; uint32_t res_a; N8_Buffer_t *input_p = NULL; uint32_t input_a; N8_Buffer_t *ctx_p = NULL; uint32_t ctx_a = 0; int nBytes; unsigned int numCommands = 0; unsigned int numCtxBytes = 0; N8_MemoryHandle_t *request_p; n8_ctxLoadFcn_t ctxLoadFcn; n8_SSLTLSFcn_t encryptFcn; do { /* verify the pointers passed in are not null */ CHECK_OBJECT(packetObj_p, ret); CHECK_STRUCTURE(packetObj_p->structureID, N8_PACKET_STRUCT_ID, ret); CHECK_OBJECT(packet_p, ret); CHECK_OBJECT(result_p, ret); request_p = (N8_MemoryHandle_t *) request; /* Check that request_p & mode are consistent */ if (request_p == NULL) { if (packetObj_p->mode != N8_PACKETMEMORY_NONE) { /* No request_p means mode should be "none" */ ret = N8_INCONSISTENT; break; } } else if (packetObj_p->mode != N8_PACKETMEMORY_REQUEST) { /* They said they would give us a request and they didn't */ ret = N8_INCONSISTENT; break; } /* * convert the length from network order to host order */ length = SSLTLS_EXTRACT_LENGTH(packet_p); /* check to see the data length is within range * [0..N8_SSLTLS_MAX_DATA_SIZE_ENCRYPT] */ if (length > N8_SSLTLS_MAX_DATA_SIZE_ENCRYPT) { ret = N8_INVALID_INPUT_SIZE; break; } numCommands = packetObj_p->encCommands; if (packetObj_p->contextLoadNeeded == N8_TRUE) { numCommands += packetObj_p->ctxLoadCmds; numCtxBytes = NEXT_WORD_SIZE(sizeof(EA_ARC4_CTX)); } /* create a kernel memory structure for temporarily storing the results */ /* compute the lengths for the result packet */ encLen = N8_ComputeEncryptedLength(length, packetObj_p->hashPacket.hashSize, packetObj_p->packetCipher); packetLen = encLen + SSLTLS_HEADER_LEN; /* compute the total number of bytes in kernel space we need to allocate. * note we round up to the next word boundary. */ /* Note that if the in packet is NULL, we don't check the out packet */ if (request_p == NULL) { nBytes = (NEXT_WORD_SIZE(length) + /* input */ NEXT_WORD_SIZE(encLen) + /* output */ numCtxBytes); /* size of context, if needed */ /* create an API request buffer */ ret = createEARequestBuffer(&req_p, packetObj_p->unitID, numCommands, resultHandlerSSLTLSEncrypt, nBytes); CHECK_RETURN(ret); /* User has not provided a request buffer */ res_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset); res_a = req_p->qr.physicalAddress + req_p->dataoffset; input_p = res_p + NEXT_WORD_SIZE(length); input_a = res_a + NEXT_WORD_SIZE(length); ctx_p = input_p + NEXT_WORD_SIZE(encLen); ctx_a = input_a + NEXT_WORD_SIZE(encLen); } else { /* The user has given us a request structure. We just need to initialize it. */ req_p = (API_Request_t *) request_p->VirtualAddress; initializeEARequestBuffer(req_p, request_p, packetObj_p->unitID, numCommands, resultHandlerSSLTLSEncrypt, N8_TRUE); /* User has provided a request packet, which must contain enough space for the input and output packets. The user may reuse the input pointer for the output. */ input_p = (N8_Buffer_t *)((unsigned long) packet_p + SSLTLS_DATA_OFFSET); input_a = N8_VirtToPhys(input_p); res_p = (N8_Buffer_t *)((unsigned long) result_p + SSLTLS_DATA_OFFSET); res_a = N8_VirtToPhys(res_p); /* If we are loading context memory, we load it at the last N8_CTX_BYTES before the data section */ if (numCtxBytes > 0) { ctx_p = (N8_Buffer_t *)((unsigned long) req_p + sizeof(API_Request_t) + N8_COMMAND_BLOCK_BYTES); ctx_a = N8_VirtToPhys(ctx_p); } } next_cb_p = req_p->EA_CommandBlock_ptr; /* generate the command blocks necessary to load the context, if required */ if (packetObj_p->contextLoadNeeded == N8_TRUE) { /* Generate the command blocks for the Context Load */ ctxLoadFcn = (n8_ctxLoadFcn_t)packetObj_p->ctxLoadFcn; ret = ctxLoadFcn(req_p, next_cb_p, packetObj_p, &packetObj_p->cipherInfo, packetObj_p->packetHashAlgorithm, ctx_p, ctx_a, &next_cb_p); CHECK_RETURN(ret); packetObj_p->contextLoadNeeded = N8_FALSE; } req_p->copyBackFrom_p = res_p; req_p->postProcessingData_p = (void *) packetObj_p; /* This sets up the offset for the start of the copy back of the IV */ req_p->postProcessBuffer[0] = encLen - N8_DES_KEY_LENGTH; if (request_p == NULL) { memcpy(input_p, &packet_p[SSLTLS_DATA_OFFSET], length); req_p->copyBackTo_p = &result_p[SSLTLS_DATA_OFFSET]; req_p->copyBackSize = encLen; } else { req_p->copyBackSize = 0; } /* Generate the command blocks for the Encrypt */ encryptFcn = (n8_SSLTLSFcn_t)packetObj_p->SSLTLScmdFcn; ret = encryptFcn(next_cb_p, packetObj_p, packet_p, input_a, res_a, packetObj_p->encOpCode); CHECK_RETURN(ret); /* set up the return packet. note that this can be done before the * command is executed as it is only constant header information. */ memcpy(&result_p[SSLTLS_TYPE_OFFSET], &packet_p[SSLTLS_TYPE_OFFSET], sizeof(uint8_t) + sizeof(uint16_t)); SSLTLS_SET_LENGTH(result_p, encLen); QUEUE_AND_CHECK(event_p, req_p, ret); HANDLE_EVENT(event_p, req_p, ret); } while (FALSE); /* clean up if necessary. note that if there is no error condition, the * request will be de-allocated in the result handler. */ if (ret != N8_STATUS_OK) { freeRequest(req_p); } return ret; } /* N8_SSLEncryptAuthenticateMemory */
void* handleConnection(void* aCon) { connection con = *( (connection*) aCon ); printf( "\nConnection with client %d established.", con ); char* buffer; if ( readHttpRequest( con, &buffer ) != 0 ) { //printf( "\nError reading message." ); sendHttpResponse( con, 500, ERROR_500 ); end_contact( con ); return 0; } struct Request req = parseRequest( buffer ); printf( "\nReceived request from client:" ); printRequestData( &req ); if ( req.invalid != 0 ) { printf( "\nInvalid request: %s", buffer ); sendHttpResponse( con, 400, ERROR_400 ); freeRequest( &req ); end_contact( con ); return 0; } free( buffer ); checkCommandValid( &req ); if ( req.invalid != 0 ) { printf( "\nInvalid command: %s", req.command ); sendHttpResponse( con, 405, ERROR_405 ); freeRequest( &req ); end_contact( con ); return 0; } checkPathValid( &req ); if ( req.invalid != 0 ) { printf( "\nInvalid path requested: %s", req.path ); sendHttpResponse( con, 403, ERROR_403 ); freeRequest( &req ); end_contact( con ); return 0; } getFullPath( &req ); if ( req.invalid != 0 ) { printf( "\nUnknown file: %s", req.path ); sendHttpResponse( con, 404, ERROR_404 ); freeRequest( &req ); end_contact( con ); return 0; } FILE * fd = fopen( req.path, "r" ); if( !fd ) { printf( "\nCould not open file: %s", req.path ); sendHttpResponse( con, 403, ERROR_403 ); freeRequest( &req ); end_contact( con ); return 0; } if( sendHttpResponse( con, 200, STATUS_200 ) ); { int num_bytes = 0; char * readbuf = malloc( 1024 ); while( !feof( fd ) ) { num_bytes = fread( readbuf, 1, 1, fd ); if( num_bytes < 0 ) break; if( write( con, readbuf, num_bytes ) < 0 ) break; } write( con, "\r\n\r\n", 4 ); fclose( fd ); free( readbuf ); } printf( "\nClosing Connection %d", con); end_contact( con ); return 0; }
/** @ingroup n8_ssltls * @brief Decrypt and verify an entire SSL or TLS message. * * Decrypt an verify a SSL or TLS message. If the verification fails, it will * be noted in the return value. * * @param packetObj_p RW: Pre-initialized packet object. * @param packet_p RO: A complete, encrypted SSL or TLS packet * including the header. * @param computedMAC_p RW: Pointer to result space for the MAC * computation output. * @param verify_p: WO: Pointer to a verify flag. If the MAC's * match, the verify flag will be set to N8_TRUE. * @param result_p RW: Pointer to result space for the decrypted * result. * @param request RW: Kernel request buffer used when mode = * N8_PACKETMEMORY_REQUEST. * @param event_p RW: Asynchronous event pointer. * * @par Externals * None * * @return * Error condition if raised. * * @par Errors * N8_MALLOC_FAILED<br> * N8_INVALID_INPUT_SIZE - the value in the packet header is too large or too * small.<br> * N8_INCONSISTENT - the version number in the packet header does not * match the designation in the packet object.<br> * N8_INVALID_OBJECT - packet object is not a valid object initialized * for SSL or TLS<br> * N8_INVALID_VALUE - the value of the type field in the packet header * is not one of the legal values for SSL or TLS.<br> * * @par Assumptions * The result_p and computedMAC_p pointers refer to pre-allocated space of * sufficient size. The calling program retains responsibility for freeing this * memory. *****************************************************************************/ N8_Status_t N8_SSLTLSDecryptVerifyMemory(N8_Packet_t *packetObj_p, const N8_SSLTLSPacket_t *packet_p, N8_Buffer_t *computedMAC_p, N8_Boolean_t *verify_p, N8_SSLTLSPacket_t *result_p, N8_RequestHandle_t request, N8_Event_t *event_p) { N8_Status_t ret = N8_STATUS_OK; API_Request_t *req_p = NULL; EA_CMD_BLOCK_t *next_cb_p = NULL; N8_SSL_Post_Decrypt_Data_t *postData_p = NULL; uint16_t length; short int encLen; int nBytes; N8_Buffer_t *res_p = NULL; uint32_t res_a; N8_Buffer_t *input_p = NULL; uint32_t input_a; N8_Buffer_t *ctx_p = NULL; uint32_t ctx_a = 0; unsigned int numCommands = 0; unsigned int numCtxBytes = 0; N8_MemoryHandle_t *request_p; n8_ctxLoadFcn_t ctxLoadFcn; n8_SSLTLSFcn_t decryptFcn; do { /* ensure none of the pointers we're given are null */ CHECK_OBJECT(packetObj_p, ret); CHECK_STRUCTURE(packetObj_p->structureID, N8_PACKET_STRUCT_ID, ret); CHECK_OBJECT(packet_p, ret); #ifdef N8_MAC_COPYBACK CHECK_OBJECT(computedMAC_p, ret); #endif CHECK_OBJECT(result_p, ret); request_p = (N8_MemoryHandle_t *) request; /* Check that request_p & mode are consistent */ if (request_p == NULL) { if (packetObj_p->mode != N8_PACKETMEMORY_NONE) { /* No request_p means mode should be "none" */ ret = N8_INCONSISTENT; break; } } else if (packetObj_p->mode != N8_PACKETMEMORY_REQUEST) { /* They said they would give us a request and they didn't */ ret = N8_INCONSISTENT; break; } /* * convert the length from network order to host order */ length = ntohs(*((uint16_t *) &packet_p[SSLTLS_LENGTH_OFFSET])); /* verify the length is not greater than the max */ if (length > N8_SSLTLS_MAX_DATA_SIZE_DECRYPT) { ret = N8_INVALID_INPUT_SIZE; break; } numCommands = packetObj_p->decCommands; if (packetObj_p->contextLoadNeeded == N8_TRUE) { numCommands += packetObj_p->ctxLoadCmds; numCtxBytes = NEXT_WORD_SIZE(sizeof(EA_ARC4_CTX)); } encLen = N8_ComputeEncryptedLength(length, packetObj_p->hashPacket.hashSize, packetObj_p->packetCipher); /* kernel space is needed for the data portion of the incoming packet plus * the hash and padding. the exact amount is needed for the return * packet. */ /* Note that if the in packet is NULL, we don't check the out packet */ if (request_p == NULL) { nBytes = NEXT_WORD_SIZE(length) * 2 + numCtxBytes; /* create an API request buffer */ ret = createEARequestBuffer(&req_p, packetObj_p->unitID, numCommands, resultHandlerSSLTLSDecrypt, nBytes); CHECK_RETURN(ret); /* User has not provided any buffers */ res_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset); res_a = req_p->qr.physicalAddress + req_p->dataoffset; input_p = res_p + NEXT_WORD_SIZE(length); input_a = res_a + NEXT_WORD_SIZE(length); ctx_p = input_p + NEXT_WORD_SIZE(encLen); ctx_a = input_a + NEXT_WORD_SIZE(encLen); } else { /* User has provided a request packet, which must contain enough space for the input and output packets. The user may reuse the input pointer for the output. */ /* The user has given us a request structure. We just need to initialize it. */ req_p = (API_Request_t *) request_p->VirtualAddress; initializeEARequestBuffer(req_p, request_p, packetObj_p->unitID, numCommands, resultHandlerSSLTLSDecrypt, N8_TRUE); /* Initialize input_p and input_a to the beginning of data area in the request */ input_p = (N8_Buffer_t *)((unsigned long) packet_p + SSLTLS_DATA_OFFSET); input_a = N8_VirtToPhys(input_p); res_p = result_p + SSLTLS_DATA_OFFSET; res_a = N8_VirtToPhys(res_p); /* If we are loading context memory, we load it at the last N8_CTX_BYTES before the data section */ if (numCtxBytes > 0) { ctx_p = (N8_Buffer_t *)((unsigned long) req_p + sizeof(API_Request_t) + N8_COMMAND_BLOCK_BYTES); ctx_a = N8_VirtToPhys(ctx_p); } } next_cb_p = req_p->EA_CommandBlock_ptr; /* generate the command blocks necessary to load the context, if required */ if (packetObj_p->contextLoadNeeded == N8_TRUE) { /* Generate the command blocks for the Context Load */ ctxLoadFcn = (n8_ctxLoadFcn_t)packetObj_p->ctxLoadFcn; ret = ctxLoadFcn(req_p, req_p->EA_CommandBlock_ptr, packetObj_p, &packetObj_p->cipherInfo, packetObj_p->packetHashAlgorithm, ctx_p, ctx_a, &next_cb_p); CHECK_RETURN(ret); packetObj_p->contextLoadNeeded = N8_FALSE; } /* copy the data portion of the incoming packet into the input kernel * buffer */ if (request_p == NULL) { memcpy(input_p, &packet_p[SSLTLS_DATA_OFFSET], length); } /* use the post processing structure in the API Request */ postData_p = (N8_SSL_Post_Decrypt_Data_t *)&req_p->postProcessBuffer; /* now check the length */ if (length < packetObj_p->minLength) { ret = N8_INVALID_INPUT_SIZE; break; } /* if des, ensure the length is a multiple of N8_DES_BLOCK_MULTIPLE */ if ((packetObj_p->packetCipher == N8_CIPHER_DES) && ((length % N8_DES_BLOCK_MULTIPLE) != 0)) { ret = N8_INVALID_INPUT_SIZE; break; } /* set up the copy back for the result packet. we only copy back the data * portion which we get from the kernel buffer. */ req_p->copyBackTo_p = &result_p[SSLTLS_DATA_OFFSET]; req_p->copyBackFrom_p = res_p; /* the length the decrypted data is not known until after the operation is * run. we will calculate it in the resultHandler. set the copyBackSize * to zero as a safe thing to do.*/ req_p->copyBackSize = 0; if (packetObj_p->contextHandle.inUse == N8_FALSE) { /* This sets up the offset for the start of the copy back of the IV. This case can only occur if the cipher is DES, not ARC4 */ memcpy(&postData_p->nextIV, &(packet_p[5 - N8_DES_KEY_LENGTH + length]), N8_DES_KEY_LENGTH); } /* set up the post processing data */ postData_p->macLength = packetObj_p->macLength; postData_p->computedMAC_p = computedMAC_p; postData_p->packetObj_p = packetObj_p; postData_p->verify_p = verify_p; postData_p->encryptedLength = length; if (request_p == NULL) { postData_p->copyData = N8_TRUE; } else { postData_p->copyData = N8_FALSE; } postData_p->resultPacket_p = result_p; /* tell the Queue Manager to copy back the command block results */ req_p->copyBackCommandBlock = N8_TRUE; req_p->postProcessingData_p = (void *) postData_p; /* Generate the command blocks for the Decrypt */ decryptFcn = (n8_SSLTLSFcn_t)packetObj_p->SSLTLScmdFcn; ret = decryptFcn(next_cb_p, packetObj_p, packet_p, input_a, res_a, packetObj_p->decOpCode); CHECK_RETURN(ret); /* set up the return packet * again, recall we cannot set the length in the result packet now and * will have to do it in the result handler. */ memcpy(&result_p[SSLTLS_TYPE_OFFSET], &packet_p[SSLTLS_TYPE_OFFSET], sizeof(uint8_t) + sizeof(uint16_t)); QUEUE_AND_CHECK(event_p, req_p, ret); HANDLE_EVENT(event_p, req_p, ret); } while (FALSE); /* clean up if necessary. note that if there is no error condition, the post * data and request will be de-allocated in the result handler. */ if (ret != N8_STATUS_OK) { freeRequest(req_p); } return ret; } /* N8_SSLTLSDecryptVerify */