The procedure for encoding TS24301Msg_PDU is basically the same as given above. When the message is to be encoded with security protection, however, there are a few additional requirements. These steps are not necessary when encoding a message without security protection.
For security protected messages, including SERVICE REQUEST messages (which always have integrity protection):
Initialize the NAS security context
Specify the algorithm and keys to use
Set NAS security parameters
Assign security header fields in the PDU.
Free the NAS security context when finished.
The following code illustrates these steps. It encodes an ACTIVATE DEDICATED EPS BEARER CONTEXT ACCEPT message with both integrity and confidentiality protection.
#include "TS24301Msgs.h"
#include "rt3gppsrc/rt3gppNasSec.h"
int main (int argc, char** argv)
{
TS24301Msg_PDU pdu;
TS24301Msg_ActvDedEPSBearerCtxtAcc data;
TS24301Msg_ActvDedEPSBearerCtxtAcc* pvalue = &data;
OSCTXT ctxt;
OSOCTET msgbuf[256], *msgptr;
OSSIZE len;
int i, ret;
OSCrypt128Key integKey = { ... };
OSCrypt128Key encryptKey = { ... };
/* Initialize context structure */
ret = rtInitContext (&ctxt);
if (0 != ret) {
printf ("rtInitContext failed; status = %d\n", ret);
rtxErrPrint (&ctxt);
return ret;
}
/* Initialize the NAS Security context */
ret = rtx3gppSecInitialize(&ctxt);
if (0 != ret) {
rtxErrPrint (&ctxt);
}
/* Specify the integrity and encryption algorithms and keys.
This only needs to be done the first time or when these values change
*/
ret = rtx3gppAssignAlgorithmKeys(&ctxt, &integKey, &encryptKey,
OS3GPPSecAlgorithm_AES, OS3GPPSecAlgorithm_AES);
if (0 != ret) {
rtxErrPrint (&ctxt);
}
/* Assign count, bearerId, direction in the NAS security context.
These act as input into the security algorithms.
*/
ctxt.p3gppSec->count = 15;
ctxt.p3gppSec->bearerId = 0;
ctxt.p3gppSec->direction = 0; /*uplink*/
/* Populate data structure */
asn1Init_TS24301Msg_PDU (&pdu);
/* Specify the security header is present. Populate the security header
fields. The security header's protocol discriminator is always EPS
Mobility management. The msgAuthCode field will be filled in by function
NASEnc_TS24301Msg_PDU.
*/
pdu.m.secHdrPresent = 1;
pdu.secHdr.secHdrType = TS24007L3_SecHdrType_integProtAndCipher;
pdu.secHdr.protoDiscr = TS24007L3_ProtoDiscr_epsMobMgmt;
pdu.secHdr.seqNumber = 1;
/* The skipIndicator is used for the message's ESP bearer identity;
it is always zero. The PDU's protocol discriminator (unlike the security
header's protocol discriminator above) is set according to the message
being protected.
*/
pdu.l3HdrOpts.t = T_TS24007L3_L3HdrOptions_skipInd;
pdu.l3HdrOpts.u.skipInd = 0;
pdu.protoDiscr = TS24007L3_ProtoDiscr_epsSessMgmt;
pdu.msgType = ASN1V_ts24301Msg_mt_ActvDedEPSBearerCtxtAcc;
...
/* Encode data.
NASEnc_TS24301Msg_PDU will encrypt the message and compute the message
authentication code according to the security settings chosen above.
*/
rtxCtxtSetBufPtr (&ctxt, msgbuf, sizeof(msgbuf));
ret = NASEnc_TS24301Msg_PDU (&ctxt, &pdu);
if (0 != ret) {
printf ("encode PDU failed; status = %d\n", ret);
rtxErrPrint (&ctxt);
return ret;
}
...
/* Free the NAS security context */
rtx3gppSecFree(&ctxt);
...
}
When the message being security protected is a SERVICE REQUEST message, the above procedure is basically the same, but a few differences do exist:
TS24301Msg_ServiceRequest has its own secHdr field that is simply the security header type. This means there are two fields (this one and TS24301Msg_PDU.secHdr.secHdrType) that have the security header type; both should be set to TS24007L3_SecHdrType_secHdrForSvcReq.
TS24301Msg_ServiceRequest has its own MAC field, shortMAC. This does not need to be set. It will be assigned by NASEnc_TS24301Msg_PDU (TS24301Msg_PDU.secHdr.msgAuthCode will not be assigned).