Opened 4 years ago

#4509 new defect

CreatePQ

Reported by: regicfaras Owned by:
Priority: Please fill in Component: ! Please select...
Severity: Please fill in Keywords:
Cc: Sensitive: no

Description

kann jemand dieses funktion ( * Softcam plugin to VDR (C++) ) in oscam bauen oder patch oscam

DANKE

if there is a possibility
expand 24 byt
96 byt (2 x 48 byt ) 104 byt (2 x 52 byt ) and 108 (2 x 54 byt )

# -- cNagra2 ------------------------------------------------------------------

class cNagra2 : public cNagraprivate:
  bool Signature( unsigned char *vkey, *sig, *msg, len)
protected:
  cIDEA idea
  #
  virtual void CreatePQ( unsigned char *key, *p, *q)
  bool DecryptECM( unsigned char *in, *out, *key, len, *vkey, *m)
  bool DecryptEMM( unsigned char *in, *out, *key, len, *vkey, *m)


def CreatePQ(self, *key, *p, *q):
  # Calculate P and Q from PK
  IdeaKS ks
  idea.SetEncKey(key,&ks)
  # expand IDEA-G key
  unsigned char idata[96]
  for(int i=11; i>=0; i--)    unsigned char *d=&idata[i*8]
    memcpy(d,&key[13],8)
    *d^=i
    idea.Decrypt(d,8,&ks,0)
    xxor(d,8,d,&key[13])
    *d^=i

  # Calculate P
  idata[0] |= 0x80
  idata[47] |= 1
  BN_bin2bn(idata,48,p)
  BN_add_word(p,(key[21] << 5 ) | ((key[22] & 0xf0) >> 3))
  # Calculate Q
  idata[48] |= 0x80
  idata[95] |= 1
  BN_bin2bn(idata+48,48,q)
  BN_add_word(q,((key[22]&0xf)<<9) | (key[23]<<1))


def Signature(self, *vkey, *sig, *msg, len):
  unsigned char buff[16]
  memcpy(buff,vkey,sizeof(buff))
  for(int i=0; i<len; i+=8)    IdeaKS ks
    idea.SetEncKey(buff,&ks)
    memcpy(buff,buff+8,8)
    idea.Encrypt(msg+i,8,buff+8,&ks,0)
    xxor(&buff[8],8,&buff[8],msg+i)

  buff[8]&=0x7F
  return (memcmp(sig,buff+8,8)==0)


def DecryptECM(self, *in, *out, *key, len, *vkey, *m):
  int sign=in[0] & 0x80
  if rsa.RSA(out,in+1,64,pubExp,m)<=0:    PRINTF(L_SYS_CRYPTO,"first RSA failed (ECM)")
    return False

  out[63]|=sign; # sign adjustment
  if len>64) memcpy(out+64,in+65,len-64:

  if in[0]&0x04:    unsigned char tmp[8]
    DES_key_schedule ks1, ks2; 
    RotateBytes(tmp,&key[0],8)
    DES_key_sched((DES_cblock *)tmp,&ks1)
    RotateBytes(tmp,&key[8],8)
    DES_key_sched((DES_cblock *)tmp,&ks2)
    memset(tmp,0,sizeof(tmp))
    for(int i=7; i>=0; i--) RotateBytes(out+8*i,8)
    DES_ede2_cbc_encrypt(out,out,len,&ks1,&ks2,(DES_cblock *)tmp,DES_DECRYPT)
    for(int i=7; i>=0; i--) RotateBytes(out+8*i,8)
    } 
  else idea.Decrypt(out,len,key,0); 

  RotateBytes(out,64)
  if rsa.RSA(out,out,64,pubExp,m,False)<=0:    PRINTF(L_SYS_CRYPTO,"second RSA failed (ECM)")
    return False

  if vkey and not Signature(vkey,out,out+8,len-8):    PRINTF(L_SYS_CRYPTO,"signature failed (ECM)")
    return False

  return True


def DecryptEMM(self, *in, *out, *key, len, *vkey, *m):
  int sign=in[0]&0x80
  if rsa.RSA(out,in+1,96,pubExp,m)<=0:    PRINTF(L_SYS_CRYPTO,"first RSA failed (EMM)")
    return False

  out[95]|=sign; # sign adjustment
  cBN exp
  if in[0]&0x08:    # standard IDEA decrypt
    if len>96) memcpy(out+96,in+97,len-96:
    idea.Decrypt(out,len,key,0)
    BN_set_word(exp,3)

  else:
    # private RSA key expansion
    CreateRSAPair(key,0,exp,m)

  RotateBytes(out,96)
  if rsa.RSA(out,out,96,exp,m,False)<=0:    PRINTF(L_SYS_CRYPTO,"second RSA failed (EMM)")
    return False

  if vkey and not Signature(vkey,out,out+8,len-8):    PRINTF(L_SYS_CRYPTO,"signature failed (EMM)")
    return False

  return True


# -- cSystemNagra2 ------------------------------------------------------------

static int dropEMMs=1

class cSystemNagra2 : public cSystem, cNagra2private:
  int lastEcmId, lastEmmId
  cN2Prov *ecmP, *emmP
public:
  cSystemNagra2(void)
  ~cSystemNagra2()
  virtual bool ProcessECM( cEcmInfo *ecm, *data)
  virtual void ProcessEMM(int pid, caid, *buffer)


cSystemNagra2.cSystemNagra2(void)
:cSystem(SYSTEM_NAME,SYSTEM_PRI)
  hasLogger=True
  lastEcmId=lastEmmId=0; ecmP=emmP=0


cSystemNagra2.~cSystemNagra2()
  delete ecmP
  delete emmP


def ProcessECM(self, *ecm, *data):
#define NA_SOURCE_START 0x8267 # cSource.FromString("S61.5W")
#define NA_SOURCE_END   0x85c8 # cSource.FromString("S148W")
  unsigned char odata[15]
  memcpy(odata,data,sizeof(odata))
  if ecm.source>=NA_SOURCE_START and ecm.source<=NA_SOURCE_END:    if(ecm.caId==0x1234) data[5]=0x09;		# NA rev 248 morph
    else:
      if(ecm.source==0x83ca) data[5]=0xC1;     # 97W
      elif(ecm.source==0x8334 or ecm.source==0x838e) data[5]=0x09; # 82W 91W
      else data[5]=0x01

    data[6]&=0x1F
    data[7]=(data[7]&0x10)|0x86
    data[8]=0
    data[9]=(data[9]&0x80)|0x08


  int cmdLen=data[4]-5
  int id=(data[5]*256)+data[6]
  cTimeMs minTime

  if(id==0x4101) StartLog(ecm,0x1881); # D+ AU
  if(id==0x0505 or id==0x0503 or id==0x0511) id=0x0501; # PremStar  ugly again :(

  if cmdLen<64 or SCT_LEN(data)<cmdLen+10:    if doLog) PRINTF(L_SYS_ECM,"bad ECM message msgLen=%d sctLen=%d",cmdLen,SCT_LEN(data):
    return False


  int keyNr=(data[7]&0x10)>>4
  cKeySnoop ks(self,'N',id,keyNr)
  cPlainKey *pk
  cBN m1
  unsigned char ideaKey[16], vKey[16]
  bool hasVerifyKey=False
  if not (pk=keys.FindKey('N',id,MBC('M','1'),-1)):    if doLog) PRINTF(L_SYS_KEY,"missing %04x M1 key",id:
    return False

  pk.Get(m1)
  if pk=keys.FindKeyNoTrig('N',id,'V',sizeof(vKey))):    pk.Get(vKey:
    hasVerifyKey=True

  elif doLog and id!=lastEcmId) PRINTF(L_SYS_KEY,"missing %04x V key (non-fatal)",id:
  if(not (pk=keys.FindKey('N',id,keyNr,sizeof(ideaKey)))) return False
  pk.Get(ideaKey)

  unsigned char buff[256]
  if not DecryptECM(data+9,buff,ideaKey,cmdLen,hasVerifyKey?vKey:0,m1):    if doLog) PRINTF(L_SYS_ECM,"decrypt of ECM failed (%04x)",id:
    return False


  if (not ecmP and id!=lastEcmId) or (ecmP and not ecmP.CanHandle(id)):    delete ecmP
    ecmP=cN2Providers.GetProv(id,N2FLAG_NONE)
    if ecmP) ecmP.PrintCaps(L_SYS_ECM:

  lastEcmId=id
  if ecmP) ecmP.PostDecrypt(True:

  HEXDUMP(L_SYS_RAWECM,buff,cmdLen,"Nagra2 RAWECM")
  int l=0, mecmAlgo=0
  LBSTARTF(L_SYS_ECM)
  bool contFail=False
  for(int i=(buff[14]&0x10)?16:20; i<cmdLen-10 and l!=3; )    switch(buff[i])      case 0x10:
      case 0x11:
        if buff[i+1]==0x09:          int s=(~buff[i])&1
          mecmAlgo=buff[i+2]&0x60
          memcpy(cw+(s<<3),&buff[i+3],8)
          i+=11; l|=(s+1)

        else:
          PRINTF(L_SYS_ECM,"bad length %d in CW nano %02x",buff[i+1],buff[i])
          i++

        break
      case 0x00:
        i+=2; break
      case 0x30:
      case 0x31:
      case 0x32:
      case 0x33:
      case 0x34:
      case 0x35:
      case 0x36:
      case 0xB0:
        i+=buff[i+1]+2
        break
      default:
        if not contFail) LBPUT("unknown ECM nano":
        LBPUT(" %02x",buff[i])
        contFail=True
        i++
        continue

    LBFLUSH(); contFail=False

  LBEND()
  if(l!=3) return False
  if mecmAlgo>0:    if ecmP and ecmP.HasFlags(N2FLAG_MECM):      if(not ecmP.MECM(buff[15],mecmAlgo,odata,cw)) return False

    else { PRINTF(L_SYS_ECM,"MECM for provider %04x not supported",id); return False

  if ecmP) ecmP.SwapCW(cw:
  ks.OK(pk)

  int i=minEcmTime-minTime.Elapsed()
  if i>0) cCondWait.SleepMs(i:
  return True


def ProcessEMM(self, pid, caid, *buffer):
  int cmdLen=buffer[9]-5
  int id=buffer[10]*256+buffer[11]

  if(buffer[0]==0x83 and dropEMMs) return; # skip EMM-S if disabled
  if cmdLen<96 or SCT_LEN(buffer)<cmdLen+15:    PRINTF(L_SYS_EMM,"bad EMM message msgLen=%d sctLen=%d",cmdLen,SCT_LEN(buffer))
    return


  int keyset=(buffer[12]&0x03)
  int sel=(buffer[12]&0x10)<<2
  int rsasel=(MATCH_ID(id,0x4101) or MATCH_ID(id,0x7101)) ? 0:sel; # D+ hack
  int sigsel=(buffer[13]&0x80)>>1
  cPlainKey *pk
  cBN n
  unsigned char ideaKey[24], vKey[16]
  bool hasVerifyKey=False
  if not (pk=keys.FindKeyNoTrig('N',id,MBC(N2_MAGIC,keyset+0x10+rsasel),96)):    PRINTF(L_SYS_EMM,"missing %04x NN %.02X RSA key (96 bytes)",id,keyset+0x10+rsasel)
    return

  pk.Get(n)
  if pk=keys.FindKeyNoTrig('N',id,MBC(N2_MAGIC,0x03+sigsel),sizeof(vKey))):    pk.Get(vKey:
    hasVerifyKey=True

  elif id!=lastEmmId) PRINTF(L_SYS_EMM,"missing %04x NN %.02X signature key (non-fatal)",id,0x03+sigsel:
  if not (pk=keys.FindKeyNoTrig('N',id,MBC(N2_MAGIC,keyset),24)):    if not (pk=keys.FindKeyNoTrig('N',id,MBC(N2_MAGIC,keyset+sel),16)):      PRINTF(L_SYS_EMM,"missing %04x NN %.02x IDEA key (24 or 16 bytes)",id,keyset+sel)
      return

    memset(ideaKey+16,0,8)

  pk.Get(ideaKey)

  unsigned char emmdata[256]
  if not DecryptEMM(buffer+14,emmdata,ideaKey,cmdLen,hasVerifyKey?vKey:0,n):    PRINTF(L_SYS_EMM,"decrypt of EMM failed (%04x)",id)
    return

  if (not emmP and id!=lastEmmId) or (emmP and not emmP.CanHandle(id)):    delete emmP
    emmP=cN2Providers.GetProv(id,N2FLAG_NONE)
    if emmP) emmP.PrintCaps(L_SYS_EMM:

  lastEmmId=id
  if emmP) emmP.PostDecrypt(False:

  HEXDUMP(L_SYS_RAWEMM,emmdata,cmdLen,"Nagra2 RAWEMM")
  if(buffer[0]==0x82) id=(emmdata[8]<<8)+emmdata[9]
  LBSTARTF(L_SYS_EMM)
  bool contFail=False
  for(int i=8+2+4+4; i<cmdLen-22; )    switch(emmdata[i])      case 0x42: # plain Key update
        if (((emmdata[i+3]|0xF3)+1)&0xFF) != 0:          int len=emmdata[i+2]
          int off=emmdata[i+5]
          int ulen=emmdata[i+6]
          if len>0 and ulen>0 and off+ulen<=len:            int ks=emmdata[i+3], kn
            if ks==0x06 or ks==0x46) kn=(ks>>6)&1; else kn=MBC(N2_MAGIC,ks:
            unsigned char key[256]
            memset(key,0,sizeof(key))
            if pk=keys.FindKeyNoTrig('N',id,kn,len)):              if(cPlainKeyNagra.IsBNKey(kn)) { pk.Get(n); n.PutLE(key,len:
              else pk.Get(key)

            bool ok=False
            if((emmdata[i+1]&0x7F)==0) ok=True
            else:
              if emmP and emmP.HasFlags(N2FLAG_POSTAU):                if(emmP.PostProcAU(id,&emmdata[i])) ok=True

              else PRINTF(L_SYS_EMM,"POSTAU for provider %04x not supported",id)

            if ok:              memcpy(&key[off],&emmdata[i+7],ulen)
              FoundKey()
              if cPlainKeyNagra.IsBNKey(kn):                n.GetLE(key,len)
                if keys.NewKey('N',id,kn,n,len)) NewKey(:

              else:
                if keys.NewKey('N',id,kn,key,len)) NewKey(:


            i+=ulen

          else PRINTF(L_SYS_EMM,"nano42 key size mismatch len=%d off=%d ulen=%d",len,off,ulen)

        else PRINTF(L_SYS_EMM,"nano42 0xf3 status exceeded")
        i+=7
        break
      case 0xE0: # DN key update
        if emmdata[i+1]==0x25:          FoundKey()
          if keys.NewKey('N',id,(emmdata[i+16]&0x40)>>6,&emmdata[i+23],16)) NewKey(:

        i+=emmdata[i+1]+2
        break
      case 0x83: # change data prov. id
        id=(emmdata[i+1]<<8)|emmdata[i+2]
        i+=3
        break
      case 0xB0: case 0xB1: case 0xB2: case 0xB3: # Update with ROM CPU code
      case 0xB4: case 0xB5: case 0xB6: case 0xB7:
      case 0xB8: case 0xB9: case 0xBA: case 0xBB:
      case 0xBC: case 0xBD: case 0xBE: case 0xBF:
        int bx=emmdata[i]&15
        if not emmP or not emmP.HasFlags(N2FLAG_Bx):          PRINTF(L_SYS_EMM,"B%X for provider %04x not supported",bx,id)
          i=cmdLen
          break

        int r
        if (r=emmP.ProcessBx(emmdata,cmdLen,i+1))>0:
          i+=r
        else:
          PRINTF(L_SYS_EMM,"B%X executing failed for %04x",bx,id)
          i=cmdLen

        break

      case 0xA0: i+=5; break;                   # CamID target update
      case 0xA3: i+=4; break;                   # Cam group target update
      case 0xA4: i+=emmdata[i+1]+2+4; break;	# conditional (always no match assumed for now)
      case 0xA6:                                # updates tier/blackout
        if emmdata[i+4]==0xFD and emmdata[i+5]==0x98) i+=(emmdata[i+1]+emmdata[i+3]+4:
        else i+=15
        break
      case 0xAA: i+=emmdata[i+1]+5; break
      case 0xAD: i+=emmdata[i+1]+2; break
      case 0xA2:
      case 0xAE: i+=11; break
      case 0x01: i+=3; break
      case 0x10: i+=18; break
      case 0x12: i+=emmdata[i+1]+2; break;      # create tier
      case 0x20: i+=19; break;                  # modify tier
      case 0x9F: i+=6; break
      case 0xE3:                                # Eeprom update
        int ex=emmdata[i]&15
        if not emmP or not emmP.HasFlags(N2FLAG_Ex):          i+=emmdata[i+4]+5
          PRINTF(L_SYS_EMM,"E%X for provider %04x not supported",ex,id)
          break

        int r
        if (r=emmP.ProcessEx(emmdata,cmdLen,i+1))>0:
          i+=r
        else:
          PRINTF(L_SYS_EMM,"E%X executing failed for %04x",ex,id)
          i=cmdLen

        break

      case 0x13:
      case 0x14:
      case 0x15:
      case 0x85:
      case 0xE1:
      case 0xE2:
      case 0x00: i=cmdLen; break;		# end of processing
      default:
        if not contFail) LBPUT("unknown EMM nano":
        LBPUT(" %02x",emmdata[i])
        contFail=True
        i++
        continue

    LBFLUSH(); contFail=False

  LBEND()


# -- cSystemLinkNagra2 --------------------------------------------------------

class cSystemLinkNagra2 : public cSystemLinkpublic:
  cSystemLinkNagra2(void)
  virtual bool CanHandle(unsigned short SysId)
  virtual cSystem *Create(void) { return cSystemNagra2


static cSystemLinkNagra2 staticInitN2

cSystemLinkNagra2.cSystemLinkNagra2(void)
:cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
  opts=new cOpts(SYSTEM_NAME,5)
  opts.Add(new cOptBool("DropEMMS",trNOOP("Nagra2: drop EMM-S packets"),&dropEMMs))
#ifdef HAS_AUXSRV
  static  char allowed_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz-."
  opts.Add(new cOptBool("AuxServerEnable",trNOOP("Nagra2: Enable AUXserver"),&auxEnabled))
  opts.Add(new cOptStr("AuxServerAddr",trNOOP("Nagra2: AUXserver hostname"),auxAddr,sizeof(auxAddr),allowed_chars))
  opts.Add(new cOptInt("AuxServerPort",trNOOP("Nagra2: AUXserver port"),&auxPort,0,65535))
  opts.Add(new cOptStr("AuxServerPass",trNOOP("Nagra2: AUXserver password"),auxPassword,sizeof(auxPassword),allowed_chars))
#endif
  Feature.NeedsKeyFile()


def CanHandle(self, SysId):
  return ((SysId&SYSTEM_MASK)==SYSTEM_NAGRA and (SysId&0xFF)>0) or
          SysId==SYSTEM_NAGRA_BEV

Attachments (1)

nagra2.c (36.9 KB ) - added by regicfaras 4 years ago.

Download all attachments as: .zip

Change History (1)

by regicfaras, 4 years ago

Attachment: nagra2.c added
Note: See TracTickets for help on using tickets.