int packetAddHLRCreateRequest(unsigned char *packet,int packet_maxlen,int *packet_len) { int packet_len_in=*packet_len; CHECK_PACKET_LEN(1); packet[(*packet_len)++]=ACTION_CREATEHLR; if (debug>2) dump("Variable request octets (HLR create)",&packet[packet_len_in],(*packet_len)-packet_len_in); return 0; }
int packetAddVariableWrite(unsigned char *packet,int packet_maxlen, int *packet_len, int itemId,int instance,unsigned char *value, int start_offset,int value_len,int flags) { /* Work out which item type we are asking for */ int packet_len_in=*packet_len; int max_offset=start_offset+value_len-1; if (debug>1) printf("packetAddVariableWrite(start=%d,len=%d,flags=%d)\n",start_offset,value_len,flags); /* Sanity check */ if (instance<0) return setReason("Asked for illegal variable value instance"); if (instance>0xfe) return setReason("Asked for illegal variable value instance"); if ((itemId<0x80)&&instance) return setReason("Asked for secondary value of single-value variable"); if (start_offset<0||start_offset>0xffff) return setReason("Asked for illegal variable value starting offset"); if (max_offset<0||max_offset>0xffff) return setReason("Asked for illegal variable value ending offset"); /* Add request to the packet */ CHECK_PACKET_LEN(1+1+((itemId&0x80)?1:0)+2+2+1); packet[(*packet_len)++]=ACTION_SET; packet[(*packet_len)++]=itemId; if (itemId&0x80) packet[(*packet_len)++]=instance; packet[(*packet_len)++]=start_offset>>8; packet[(*packet_len)++]=start_offset&0xff; packet[(*packet_len)++]=value_len>>8; packet[(*packet_len)++]=value_len&0xff; packet[(*packet_len)++]=flags; if (debug>2) dump("Packet with var write header",&packet[0],*packet_len); CHECK_PACKET_LEN(value_len); bcopy(&value[0],&packet[*packet_len],value_len); (*packet_len)+=value_len; if (debug>2) dump("Variable request octets (write)",&packet[packet_len_in],(*packet_len)-packet_len_in); return 0; }
int packetFinalise(unsigned char *packet,int packet_maxlen,int *packet_len) { /* Add any padding bytes and EOT to packet */ int paddingBytes=rand()&0xf; int payloadRotation; if (paddingBytes) { CHECK_PACKET_LEN(2+paddingBytes); packet[(*packet_len)++]=ACTION_PAD; packet[(*packet_len)++]=paddingBytes; while(paddingBytes--) packet[(*packet_len)++]=random()&0xff; } packet[(*packet_len)++]=ACTION_EOT; /* Set payload length */ packet[4]=((*packet_len)>>8)&0xff; packet[5]=((*packet_len)&0xff); /* Work out by how much to rotate the packet payload. The purpose of the rotation is to make it more difficult to conduct a known-plaintext attack against any ciphers that we may later support. */ payloadRotation=(*packet_len)-HEADERFIELDS_LEN; if (payloadRotation>0xff) payloadRotation=0xff; payloadRotation=random()%payloadRotation; if (debug>2) fprintf(stderr,"Known Plaintext counter-measure: rotating packet payload by 0x%02x bytes.\n", payloadRotation); if (debug>2) dump("unrotated packet",packet,*packet_len); /* Now rotate the payload */ { unsigned char temp[256]; /*Copy first part of payload to a temporary buffer */ bcopy(&packet[HEADERFIELDS_LEN],&temp[0],payloadRotation); /* Copy the main part of the payload left by the rotation factor */ bcopy(&packet[HEADERFIELDS_LEN+payloadRotation],&packet[HEADERFIELDS_LEN], (*packet_len)-(HEADERFIELDS_LEN)-payloadRotation); /* Copy the temporary buffer to the end of the packet to complete the rotation */ bcopy(&temp[0],&packet[(*packet_len)-payloadRotation],payloadRotation); } packet[OFS_ROTATIONFIELD]=payloadRotation; if (debug>3) dump("rotated packet",packet,*packet_len); return 0; }
int packetMakeHeader(unsigned char *packet,int packet_maxlen,int *packet_len, unsigned char *transaction_id,int cryptoflags) { int i; CHECK_PACKET_LEN(OFS_PAYLOAD); /* 0x4110 magic value */ packet[0]=0x41; packet[1]=0x10; /* encoding version */ packet[2]=0x00; packet[3]=0x01; /* Payload length (to be filled in later) */ packet[4]=0x00; packet[5]=0x00; /* Payload cipher (0x0000 = plain text) */ packet[6]=0x00; packet[7]=0x00; /* Add 64bit transaction id */ if (transaction_id) /* Use supplied transaction ID */ for(i=0;i<TRANSID_SIZE;i++) packet[OFS_TRANSIDFIELD+i]=transaction_id[i]; else /* No transaction ID supplied, so create random transaction ID */ for(i=0;i<TRANSID_SIZE;i++) packet[OFS_TRANSIDFIELD+i]=random()&0xff; /* payload rotation (not yet applied) */ packet[OFS_ROTATIONFIELD]=0x00; *packet_len=HEADERFIELDS_LEN; /* Clear did/subscriber ID, salt and hashed pin fields. However, we cannot zero them, because that would provide significant knowable plain-text for a known plain text attack. Thus, instead we fill it with random date, but make the modulo sum of each field == 0x00 to indicate that no PIN has been provided. */ safeZeroField(packet,*packet_len,SIDDIDFIELD_LEN); *packet_len+=SIDDIDFIELD_LEN; safeZeroField(packet,*packet_len,16); *packet_len+=16; safeZeroField(packet,*packet_len,16); *packet_len+=16; return 0; }
int respondSimple(char *sid,int action,unsigned char *action_text,int action_len, unsigned char *transaction_id) { unsigned char packet[8000]; int pl=0; int *packet_len=&pl; int packet_maxlen=8000; int i; /* ACTION_ERROR is associated with an error message. For syntactic simplicity, we do not require the respondSimple() call to provide the length of the error message. */ if (action==ACTION_ERROR) { action_len=strlen((char *)action_text); /* Make sure the error text isn't too long. IF it is, trim it, as we still need to communicate the error */ if (action_len>255) action_len=255; } /* Prepare the request packet */ if (packetMakeHeader(packet,8000,packet_len,transaction_id)) return -1; if (sid&&sid[0]) { if (packetSetSid(packet,8000,packet_len,sid)) return setReason("invalid SID in reply"); } else { if (packetSetDid(packet,8000,packet_len,"")) return setReason("Could not set empty DID in reply"); } CHECK_PACKET_LEN(1+1+action_len); packet[(*packet_len)++]=action; if (action==ACTION_ERROR) packet[(*packet_len)++]=action_len; for(i=0;i<action_len;i++) packet[(*packet_len)++]=action_text[i]; if (debug>2) dump("Simple response octets",action_text,action_len); if (packetFinalise(packet,8000,packet_len)) return -1; if (debug) fprintf(stderr,"Sending response of %d bytes.\n",*packet_len); if (packetSendRequest(REQ_REPLY,packet,*packet_len,NONBATCH,transaction_id,NULL)) return -1; return 0; }
int packetAddVariableRequest(unsigned char *packet,int packet_maxlen,int *packet_len, char *item,int instance,int start_offset,int bytes) { /* Work out which item type we are asking for */ int itemId; int packet_len_in=*packet_len; for(itemId=0;vars[itemId].name;itemId++) if (!strcmp(item,vars[itemId].name)) { break; } /* Sanity check the request */ if (!vars[itemId].name) { if (debug) fprintf(stderr,"`%s' is not a known HLR variable.\n",item); return setReason("Requested unknown HLR variable"); } itemId=vars[itemId].id; if (instance<-1) return setReason("Asked for illegal variable value instance"); if (instance>0xfe) return setReason("Asked for illegal variable value instance"); if ((itemId<0x80)&&instance) return setReason("Asked for secondary value of single-value variable"); if (start_offset<0||start_offset>0xffff) return setReason("Asked for illegal variable value starting offset"); if (bytes<0||(start_offset+bytes)>0xffff) { if (debug) fprintf(stderr,"Asked for %d bytes at offset %d\n",bytes,start_offset); return setReason("Asked for illegal variable value ending offset"); } /* Add request to the packet */ CHECK_PACKET_LEN(1+1+((itemId&0x80)?1:0)+2+2); packet[(*packet_len)++]=ACTION_GET; packet[(*packet_len)++]=itemId; if (instance==-1) instance=0xff; if (itemId&0x80) packet[(*packet_len)++]=instance; packet[(*packet_len)++]=start_offset>>8; packet[(*packet_len)++]=start_offset&0xff; packet[(*packet_len)++]=bytes>>8; packet[(*packet_len)++]=bytes&0xff; if (debug>2) dump("Variable request octets (var)",&packet[packet_len_in],(*packet_len)-packet_len_in); return 0; }
int packetFinalise(unsigned char *packet,int packet_maxlen,int recvttl, int *packet_len,int cryptoflags) { /* Add any padding bytes and EOT to packet */ int paddingBytes=rand()&0xf; int payloadRotation; if (paddingBytes) { CHECK_PACKET_LEN(2+paddingBytes); packet[(*packet_len)++]=ACTION_PAD; packet[(*packet_len)++]=paddingBytes; while(paddingBytes--) packet[(*packet_len)++]=random()&0xff; } /* tell requester what the ttl was when we received the packet */ if (recvttl>-1) { CHECK_PACKET_LEN(2); packet[(*packet_len)++]=ACTION_RECVTTL; packet[(*packet_len)++]=recvttl; } /* mark end of packet */ CHECK_PACKET_LEN(1); packet[(*packet_len)++]=ACTION_EOT; /* Set payload length */ packet[4]=((*packet_len)>>8)&0xff; packet[5]=((*packet_len)&0xff); /* Work out by how much to rotate the packet payload. The purpose of the rotation is to make it more difficult to conduct a known-plaintext attack against any ciphers that we may later support. */ payloadRotation=(*packet_len)-HEADERFIELDS_LEN; if (payloadRotation>0xff) payloadRotation=0xff; payloadRotation=random()%payloadRotation; if (debug&DEBUG_SECURITY) { DEBUGF("Known Plaintext counter-measure: rotating packet payload by 0x%02x bytes", payloadRotation); dump("unrotated packet",packet,*packet_len); } /* Now rotate the payload */ { unsigned char temp[256]; /*Copy first part of payload to a temporary buffer */ bcopy(&packet[HEADERFIELDS_LEN],&temp[0],payloadRotation); /* Copy the main part of the payload left by the rotation factor */ bcopy(&packet[HEADERFIELDS_LEN+payloadRotation],&packet[HEADERFIELDS_LEN], (*packet_len)-(HEADERFIELDS_LEN)-payloadRotation); /* Copy the temporary buffer to the end of the packet to complete the rotation */ bcopy(&temp[0],&packet[(*packet_len)-payloadRotation],payloadRotation); } packet[OFS_ROTATIONFIELD]=payloadRotation; if (debug&DEBUG_SECURITY) dump("rotated packet",packet,*packet_len); if (cryptoflags) return packetEncipher(packet,packet_maxlen,packet_len,cryptoflags); return 0; }