/ keychain / SecureObjectSync / SOSRingV0.m
SOSRingV0.m
  1  //
  2  //  SOSRingV0.c
  3  //  sec
  4  //
  5  //  Created by Richard Murphy on 3/5/15.
  6  //
  7  //
  8  
  9  #include "SOSRingV0.h"
 10  
 11  #include <AssertMacros.h>
 12  
 13  #include "keychain/SecureObjectSync/SOSInternal.h"
 14  #include "keychain/SecureObjectSync/SOSPeerInfoInternal.h"
 15  #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
 16  #include "keychain/SecureObjectSync/SOSCircle.h"
 17  #include <Security/SecFramework.h>
 18  
 19  #include <Security/SecKey.h>
 20  #include <Security/SecKeyPriv.h>
 21  #include <CoreFoundation/CoreFoundation.h>
 22  
 23  #include <utilities/SecCFWrappers.h>
 24  
 25  #include <stdlib.h>
 26  
 27  #include "SOSRingUtils.h"
 28  #include "SOSRingTypes.h"
 29  
 30  // MARK: V0 Ring Ops - same operation as V0 Circles
 31  
 32  static SOSRingRef SOSRingCreate_V0(CFStringRef name, CFStringRef myPeerID, CFErrorRef *error) {
 33      SOSRingRef retval = NULL;
 34      retval = SOSRingCreate_Internal(name, 0, error);
 35      if(!retval) return NULL;
 36      SOSRingSetLastModifier(retval, myPeerID);
 37      return retval;
 38  }
 39  
 40  static bool SOSRingResetToEmpty_V0(SOSRingRef ring, CFStringRef myPeerID, CFErrorRef *error) {
 41      return SOSRingResetToEmpty_Internal(ring, error) && SOSRingSetLastModifier(ring, myPeerID);
 42  }
 43  
 44  static bool SOSRingResetToOffering_V0(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
 45      CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
 46      SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error);
 47      bool retval = priv && myPeerID &&
 48      SOSRingResetToEmpty_Internal(ring, error) &&
 49      SOSRingAddPeerID(ring, myPeerID) &&
 50      SOSRingSetLastModifier(ring, myPeerID) &&
 51      SOSRingGenerationSign_Internal(ring, user_privkey, error);
 52      SOSRingConcordanceSign_Internal(ring, priv, error);
 53      CFReleaseNull(priv);
 54      return retval;
 55  }
 56  
 57  static SOSRingStatus SOSRingDeviceIsInRing_V0(SOSRingRef ring, CFStringRef peerID) {
 58      if(SOSRingHasPeerID(ring, peerID)) return kSOSRingMember;
 59      if(SOSRingHasApplicant(ring, peerID)) return kSOSRingApplicant;
 60      if(SOSRingHasRejection(ring, peerID)) return kSOSRingReject;
 61      return kSOSRingNotInRing;
 62  }
 63  
 64  static bool SOSRingApply_V0(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
 65      bool retval = false;
 66      CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
 67      if(SOSRingDeviceIsInRing_V0(ring, myPeerID) == kSOSRingReject) SOSRingRemoveRejection(ring, myPeerID);
 68      require_action_quiet(SOSRingDeviceIsInRing_V0(ring, myPeerID) == kSOSRingNotInRing, errOut, secnotice("ring", "Already associated with ring"));
 69      retval = myPeerID &&
 70      SOSRingAddApplicant(ring, myPeerID) &&
 71      SOSRingSetLastModifier(ring, myPeerID);
 72  errOut:
 73      return retval;
 74  }
 75  
 76  static bool SOSRingWithdraw_V0(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
 77      CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
 78      SOSRingSetLastModifier(ring, myPeerID);
 79      if(SOSRingHasPeerID(ring, myPeerID)) {
 80          SOSRingRemovePeerID(ring, myPeerID);// Maybe we need a retired peerID list?
 81          SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error);
 82          SOSRingGenerationSign_Internal(ring, priv, error);
 83          if(user_privkey) SOSRingGenerationSign_Internal(ring, user_privkey, error);
 84          CFReleaseNull(priv);
 85      } else if(SOSRingHasApplicant(ring, myPeerID)) {
 86          SOSRingRemoveApplicant(ring, myPeerID);
 87      } else if(SOSRingHasRejection(ring, myPeerID)) {
 88          SOSRingRemoveRejection(ring, myPeerID);
 89      } else {
 90          SOSCreateError(kSOSErrorPeerNotFound, CFSTR("Not associated with Ring"), NULL, error);
 91          return false;
 92      }
 93  
 94      return true;
 95  }
 96  
 97  static bool SOSRingGenerationSign_V0(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
 98      CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
 99      SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error);
100      bool retval = priv && myPeerID &&
101      SOSRingSetLastModifier(ring, myPeerID) &&
102      SOSRingGenerationSign_Internal(ring, priv, error);
103      if(user_privkey) SOSRingGenerationSign_Internal(ring, user_privkey, error);
104      CFReleaseNull(priv);
105      return retval;
106  }
107  
108  static bool SOSRingConcordanceSign_V0(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
109      CFStringRef myPeerID = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(requestor));
110      SecKeyRef priv = SOSFullPeerInfoCopyDeviceKey(requestor, error);
111      bool retval = priv && myPeerID &&
112      SOSRingSetLastModifier(ring, myPeerID) &&
113      SOSRingConcordanceSign_Internal(ring, priv, error);
114      CFReleaseNull(priv);
115      return retval;
116  }
117  
118  
119  ringFuncStruct ringsV0 = {
120      "V0",
121      1,
122      SOSRingCreate_V0,
123      SOSRingResetToEmpty_V0,
124      SOSRingResetToOffering_V0,
125      SOSRingDeviceIsInRing_V0,
126      SOSRingApply_V0,
127      SOSRingWithdraw_V0,
128      SOSRingGenerationSign_V0,
129      SOSRingConcordanceSign_V0,
130      SOSRingUserKeyConcordanceTrust,
131      NULL,
132      NULL
133  };