check_blockage.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*! A module for the protocol for the user to check for the availability
  2. of a migration credential they can use in order to move to a new bucket
  3. if theirs has been blocked.
  4. The user presents their current Lox credential:
  5. - id: revealed
  6. - bucket: blinded
  7. - trust_level: revealed to be 3 or above
  8. - level_since: blinded
  9. - invites_remaining: blinded
  10. - blockages: blinded
  11. They are allowed to to this as long as they are level 3 or above. If
  12. they have too many blockages (but are level 3 or above), they will be
  13. allowed to perform this migration, but will not be able to advance to
  14. level 3 in their new bucket, so this will be their last allowed
  15. migration without rejoining the system either with a new invitation or
  16. an open invitation.
  17. They will receive in return the encrypted MAC (Pk, EncQk) for their
  18. implicit Migration Key credential with attributes id and bucket,
  19. along with a HashMap of encrypted Migration credentials. For each
  20. (from_i, to_i) in the BA's migration list, there will be an entry in
  21. the HashMap with key H1(id, from_attr_i, Qk_i) and value
  22. Enc_{H2(id, from_attr_i, Qk_i)}(to_attr_i, P_i, Q_i). Here H1 and H2
  23. are the first 16 bytes and the second 16 bytes respectively of the
  24. SHA256 hash of the input, P_i and Q_i are a MAC on the Migration
  25. credential with attributes id, from_attr_i, and to_attr_i. Qk_i is the
  26. value EncQk would decrypt to if bucket were equal to from_attr_i. */
  27. #[cfg(feature = "bridgeauth")]
  28. use super::super::dup_filter::SeenType;
  29. #[cfg(feature = "bridgeauth")]
  30. use super::super::BridgeAuth;
  31. use super::super::{scalar_u32, G};
  32. use super::errors::CredentialError;
  33. use super::level_up::MAX_LEVEL;
  34. use crate::lox_creds::{Lox, Migration, MigrationKey};
  35. use crate::migration_table;
  36. use crate::migration_table::ENC_MIGRATION_BYTES;
  37. #[cfg(feature = "bridgeauth")]
  38. use crate::migration_table::WNAF_SIZE;
  39. use cmz::*;
  40. use group::Group;
  41. #[cfg(feature = "bridgeauth")]
  42. use group::WnafBase;
  43. use rand::{CryptoRng, RngCore};
  44. use sha2::Sha512;
  45. use std::collections::HashMap;
  46. /// The minimum trust level a Lox credential must have to be allowed to
  47. /// perform this protocol.
  48. pub const MIN_TRUST_LEVEL: u32 = 3;
  49. muCMZProtocol! { check_blockage<min_trust_level, max_trust_level>,
  50. L: Lox { id: R, bucket: H, trust_level: R, level_since: H, invites_remaining: R, blockages: R },
  51. M: MigrationKey { lox_id: J, from_bucket: H} ,
  52. L.bucket = M.from_bucket,
  53. [min_trust_level..max_trust_leve].contains(L.trust_level),
  54. }
  55. pub fn request(
  56. L: Lox,
  57. mig_pubkeys: CMZPubkey<G>,
  58. ) -> Result<(check_blockage::Request, check_blockage::ClientState), CredentialError> {
  59. let mut rng = rand::thread_rng();
  60. cmz_group_init(G::hash_from_bytes::<Sha512>(b"CMZ Generator A"));
  61. // Ensure that the credenials can be correctly shown; that is, the
  62. // ids match and the Lox credential bucket matches the Migration
  63. // credential from_bucket
  64. if L.id.is_none() {
  65. return Err(CredentialError::CredentialMismatch);
  66. }
  67. // Ensure the credential can be correctly shown: it must be the case
  68. // that trust_level >= MIN_TRUST_LEVEL
  69. if let Some(tl) = L.trust_level {
  70. let level: u32 = match scalar_u32(&tl) {
  71. Some(v) => v,
  72. None => {
  73. return Err(CredentialError::InvalidField(
  74. String::from("trust_level"),
  75. String::from("could not be converted to u32"),
  76. ))
  77. }
  78. };
  79. if level < MIN_TRUST_LEVEL {
  80. return Err(CredentialError::InvalidField(
  81. String::from("trust_level"),
  82. format!("level {:?} not in range", level),
  83. ));
  84. }
  85. }
  86. let params = check_blockage::Params {
  87. min_trust_level: MIN_TRUST_LEVEL.into(),
  88. max_trust_level: (MAX_LEVEL as u32).into(),
  89. };
  90. match check_blockage::prepare(
  91. &mut rng,
  92. &L,
  93. MigrationKey::using_pubkey(&mig_pubkeys),
  94. &params,
  95. ) {
  96. Ok(req_state) => Ok(req_state),
  97. Err(e) => Err(CredentialError::CMZError(e)),
  98. }
  99. }
  100. #[cfg(feature = "bridgeauth")]
  101. impl BridgeAuth {
  102. pub fn handle_check_blockage(
  103. &mut self,
  104. req: check_blockage::Request,
  105. ) -> Result<
  106. (
  107. check_blockage::Reply,
  108. HashMap<[u8; 16], [u8; ENC_MIGRATION_BYTES]>,
  109. ),
  110. CredentialError,
  111. > {
  112. let mut rng = rand::thread_rng();
  113. let reqbytes = req.as_bytes();
  114. let recvreq = check_blockage::Request::try_from(&reqbytes[..]).unwrap();
  115. match check_blockage::handle(
  116. &mut rng,
  117. recvreq,
  118. |L: &mut Lox, M: &mut MigrationKey| {
  119. L.set_privkey(&self.lox_priv);
  120. M.set_privkey(&self.migrationkey_priv);
  121. M.lox_id = L.id;
  122. M.from_bucket = L.bucket;
  123. Ok(check_blockage::Params {
  124. min_trust_level: MIN_TRUST_LEVEL.into(),
  125. max_trust_level: (MAX_LEVEL as u32).into(),
  126. })
  127. },
  128. |L: &Lox, _M: &MigrationKey| {
  129. if self.id_filter.filter(&L.id.unwrap()) == SeenType::Seen {
  130. return Err(CMZError::RevealAttrMissing("id", "Credential Expired"));
  131. }
  132. Ok(())
  133. },
  134. ) {
  135. Ok((response, (L_issuer, M_issuer))) => {
  136. let Pktable: WnafBase<G, WNAF_SIZE> = WnafBase::new(M_issuer.MAC.P);
  137. let enc_migration_table = self.blockage_migration_table.encrypt_table(
  138. L_issuer.id.unwrap(),
  139. &self.bridge_table,
  140. &Pktable,
  141. &self.migration_priv,
  142. &self.migrationkey_priv,
  143. );
  144. Ok((response, enc_migration_table))
  145. }
  146. Err(e) => Err(CredentialError::CMZError(e)),
  147. }
  148. }
  149. }
  150. pub fn handle_response(
  151. migration_pubkey: CMZPubkey<G>,
  152. state: check_blockage::ClientState,
  153. rep: check_blockage::Reply,
  154. enc_migration_table: HashMap<[u8; 16], [u8; ENC_MIGRATION_BYTES]>,
  155. ) -> Result<Migration, CMZError> {
  156. let replybytes = rep.as_bytes();
  157. let recvreply = check_blockage::Reply::try_from(&replybytes[..]).unwrap();
  158. let migkey = match state.finalize(recvreply) {
  159. Ok(cred) => cred,
  160. Err(_e) => return Err(CMZError::Unknown),
  161. };
  162. match migration_table::decrypt_cred(
  163. migkey,
  164. migration_table::MigrationType::Blockage,
  165. migration_pubkey,
  166. &enc_migration_table,
  167. ) {
  168. Some(cred) => Ok(cred),
  169. None => Err(CMZError::Unknown),
  170. }
  171. }