Esempio n. 1
0
 public OscoreEvent(EventCode code, byte[] groupIdentifier, byte[] keyIdentifier, SecurityContext context, SecurityContext.EntityContext recipient)
 {
     Code             = code;
     GroupIdentifier  = groupIdentifier;
     KeyIdentifier    = keyIdentifier;
     SecurityContext  = context;
     RecipientContext = recipient;
 }
Esempio n. 2
0
        /// <summary>
        /// Given the set of inputs, perform the crptographic operations that are needed
        /// to build a security context for a single sender and recipient.
        /// </summary>
        /// <param name="masterSecret">pre-shared key</param>
        /// <param name="senderId">name assigned to sender</param>
        /// <param name="recipientId">name assigned to recipient</param>
        /// <param name="masterSalt">salt value</param>
        /// <param name="algAEAD">encryption algorithm</param>
        /// <param name="algKeyAgree">key agreement algorithm</param>
        /// <returns></returns>
        public static SecurityContext DeriveContext(byte[] masterSecret, byte[] senderId, byte[] recipientId, byte[] masterSalt = null, CBORObject algAEAD = null, CBORObject algKeyAgree = null)
        {
            int             cbKey;
            int             cbIV;
            SecurityContext ctx = new SecurityContext();

            if (algAEAD == null)
            {
                ctx.Sender.Algorithm = AlgorithmValues.AES_CCM_16_64_128;
            }
            else
            {
                ctx.Sender.Algorithm = algAEAD;
            }

            if (ctx.Sender.Algorithm.Type != CBORType.Number)
            {
                throw new Exception("Unsupported algorithm");
            }
            switch ((AlgorithmValuesInt)ctx.Sender.Algorithm.AsInt32())
            {
            case AlgorithmValuesInt.AES_CCM_16_64_128:
                cbKey = 128 / 8;
                cbIV  = 13;
                break;

            case AlgorithmValuesInt.AES_CCM_64_64_128:
                cbKey = 128 / 8;
                cbIV  = 56 / 8;
                break;

            case AlgorithmValuesInt.AES_CCM_64_128_128:
                cbKey = 128 / 8;
                cbIV  = 56 / 8;
                break;

            case AlgorithmValuesInt.AES_CCM_16_128_128:
                cbKey = 128 / 8;
                cbIV  = 13;
                break;

            case AlgorithmValuesInt.AES_GCM_128:
                cbKey = 128 / 8;
                cbIV  = 96 / 8;
                break;

            default:
                throw new Exception("Unsupported algorithm");
            }

            ctx.Sender.Id = senderId ?? throw new ArgumentNullException(nameof(senderId));

            ctx.Recipient = new EntityContext {
                Algorithm = ctx.Sender.Algorithm,
                Id        = recipientId ?? throw new ArgumentNullException(nameof(recipientId)),
                                  ReplayWindow = new ReplayWindow(0, 64)
            };


            CBORObject info = CBORObject.NewArray();

            info.Add(senderId);             // 0
            info.Add(CBORObject.Null);      // 1
            info.Add(ctx.Sender.Algorithm); // 2
            info.Add("Key");                // 3
            info.Add(cbKey);                // 4 in bytes

            IDigest sha256;

            if (algKeyAgree == null || algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_256))
            {
                sha256 = new Sha256Digest();
            }
            else if (algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_512))
            {
                sha256 = new Sha512Digest();
            }
            else
            {
                throw new ArgumentException("Unrecognized key agreement algorithm");
            }

            IDerivationFunction hkdf = new HkdfBytesGenerator(sha256);

            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));

            ctx.Sender.Key = new byte[cbKey];
            hkdf.GenerateBytes(ctx.Sender.Key, 0, ctx.Sender.Key.Length);

            info[0] = CBORObject.FromObject(recipientId);
            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));
            ctx.Recipient.Key = new byte[cbKey];
            hkdf.GenerateBytes(ctx.Recipient.Key, 0, ctx.Recipient.Key.Length);

            info[0] = CBORObject.FromObject(new byte[0]);
            info[3] = CBORObject.FromObject("IV");
            info[4] = CBORObject.FromObject(cbIV);
            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));
            ctx.Recipient.BaseIV = new byte[cbIV];
            hkdf.GenerateBytes(ctx.Recipient.BaseIV, 0, ctx.Recipient.BaseIV.Length);
            ctx.Sender.BaseIV = (byte[])ctx.Recipient.BaseIV.Clone();

            int iIv = cbIV - 5 - senderId.Length;

            if (cbIV - 6 < senderId.Length)
            {
                throw new Exception("Sender Id too long");
            }
            ctx.Sender.BaseIV[0] ^= (byte)senderId.Length;
            for (int i = 0; i < senderId.Length; i++)
            {
                ctx.Sender.BaseIV[iIv + i] ^= senderId[i];
            }

            iIv = cbIV - 5 - recipientId.Length;
            if (cbIV - 6 < recipientId.Length)
            {
                throw new Exception("Recipient Id too long");
            }
            ctx.Recipient.BaseIV[0] ^= (byte)recipientId.Length;
            for (int i = 0; i < recipientId.Length; i++)
            {
                ctx.Recipient.BaseIV[iIv + i] ^= recipientId[i];
            }

            //  Give a unique context number for doing comparisons

            ctx.ContextNo   = _ContextNumber;
            _ContextNumber += 1;

            return(ctx);
        }